﻿var MediaSyndicationWidget = (function () {
	var jQueryCallbacks = [];
	var cssIncluded = false;

	var markup = {
		main: '<div class="mainView"><div class="innerContainer"><div class="headerSection"><div class="mainTitle"></div><div class="navButton prevButton"><a href="#" class="navButtonLink"></a></div><div class="navButton nextButton"><a href="#" class="navButtonLink"></a></div></div><div class="imageSection"><a class="photoPageUrl"><img class="mainImage" style="display: none" /></a><div class="endScreen" align="center" style="display: none"><table><tr><td class="accountImage"><a class="accountImageLink"><img class="endScreenImg" /></a></td><td valign="middle" class="seeMore"><a class="seeMoreLink"></a></td></tr></table></div></div><div class="footerSection"><div class="imageSelector"><div class="navButton prevButton"><a href="#" class="navButtonLink"></a></div><div class="imageListContainer"><div class="imageList"><ol></ol></div><div class="imageArrowContainer"><div class="imageArrow"></div></div></div><div class="navButton nextButton"><a href="#" class="navButtonLink"></a></div></div><div class="imageDescription"></div><table cellpadding="0" cellspacing="0" border="0" class="moreOnWhoSay"><tr><td><a class="linkIcon moreLink"></a></td><td><a class="linkText moreLink"></a></td></tr></table><div class="clearFloat"></div></div></div></div>',
		sidebar: '<div class="sidebarView"><div class="innerContainer"><div class="headerSection"><div class="mainTitle"></div><div class="navButton prevButton"><a href="#" class="navButtonLink"></a></div><div class="navButton nextButton"><a href="#" class="navButtonLink"></a></div></div><div class="imageSection"><a class="photoPageUrl"><img class="mainImage" style="display: none" /></a><div class="endScreen" align="center" style="display: none"><table><tr><td valign="middle"><div class="accountImage"><a class="accountImageLink"><img class="endScreenImg" /></a></div><div class="seeMore"><a class="seeMoreLink"></a></div></td></tr></table></div></div><div class="footerSection"><div class="imageDescription"></div><center><div class="imageSelector"><div class="navButton prevButton"><a href="#" class="navButtonLink"></a></div><div class="imageList"><ol></ol></div><div class="navButton nextButton"><a href="#" class="navButtonLink"></a></div><div class="clearFloat"></div></div><table cellpadding="0" cellspacing="0" border="0" class="moreOnWhoSay"><tr><td><a class="linkIcon moreLink"></a></td><td><a class="linkText moreLink"></a></td></tr></table></center></div></div></div>'
	};

	return {
		create: function (settings) {
			var serverUrl = 'https://api.whosay.com', cssUrl = 'http://cdn1.whosaystatic.com/widgets/photowidget/001/styles.css', visibleThumbnails = 3, animationDuration = 250;
			var settings, container, data, currentIndex = 0, startIndex = 0, defaultMaxResults = 5, defaultAvailableResults = 3;

			var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

			function trace(message) {
				if (window.console && settings.debug)
					window.console.log('Media Syndication Widget: ' + message);
			}

			function includeCss() {
				if (!cssIncluded) {
					var link = document.createElement('link');
					link.setAttribute('type', 'text/css');
					link.setAttribute('rel', 'stylesheet');
					link.setAttribute('href', cssUrl);

					var head = document.head || document.getElementsByTagName('head')[0] || document.documentElement;
					head.insertBefore(link, head.firstChild);

					cssIncluded = true;
				}
			}

			function prepareContainer() {
				if (settings.containerId) {
					container = document.getElementById(settings.containerId);
				} else if (document.readyState !== "complete") {
					var containerId = 'MediaSyndicationWidget_' + Math.ceil(Math.random() * 1000);
					document.write('<div id="' + containerId + '"></div>');
					container = document.getElementById(containerId);
				} else {
					trace('DOM is ready, but containerId is missing');
				}

				if (container)
					container.className = 'mediaSyndicationWidget';

				return !!container;
			}

			function getLinkAttrs(href) {
				return { href: href, target: settings.openLinksInCurrentWindow ? '_self' : '_blank' };
			}

			function loadImageAndFadeOut(loadImageSrc, elementToFadeOut, callback) {
				var d1 = MediaSyndicationWidget.jQuery.Deferred(), d2 = MediaSyndicationWidget.jQuery.Deferred(), image = new Image();
				MediaSyndicationWidget.jQuery.when(d1, d2).done(function () { callback(image) });

				image.onload = d1.resolve;
				image.src = loadImageSrc;

				if (elementToFadeOut.css('display') != 'none')
					elementToFadeOut.fadeOut(animationDuration, d2.resolve);
				else
					d2.resolve();
			}

			function formatDate(itemData) {
				if (!itemData.publishDate)
					return '';

				var parts = itemData.publishDate.split('-');

				if (parts.length != 3 || !months[parts[1] - 1]) {
					trace('Inccorect date format: ' + itemData.publishDate + ' (mediaId=' + itemData.mediaId + ')');
					return itemData.publishDate;
				}

				return parts[2] + ' ' + months[parts[1] - 1] + ' ' + parts[0];
			}

			function setDescription(index) {
				var itemData = data.body.photos[index];
				var descriptionContainer = MediaSyndicationWidget.jQuery(container).find('.imageDescription');

				var symbolWidth = 6;
				var description = '<b>' + (formatDate(itemData)) + ' </b><span>'
				if (itemData.caption) {
					if (descriptionContainer.width() > 0) {
						var symbolsCount = (Math.ceil(descriptionContainer.width() / symbolWidth) * 3 - 10);
						description += itemData.caption.length > symbolsCount
							? (itemData.caption.substr(0, symbolsCount) + '...' + '<a class="moreLink">more &raquo;</a>') : itemData.caption;
					} else {
						description += itemData.caption;
					}
				}
				description += '</span>';
				descriptionContainer.html(description).find('.moreLink').attr(getLinkAttrs(itemData.photoPageUrl));
			}

			function adjustImageSize(image, maxWidth, maxHeight) {
				var size = { width: image.width, height: image.height };
				var prevHeight = image.height;
				if (size.width >= maxWidth) {
					size.width = maxWidth;
					size.height = prevHeight = size.height * size.width / image.width;
				}
				if (size.height >= maxHeight) {
					size.height = maxHeight;
					size.width = size.width * size.height / prevHeight;
				}

				return size;
			}

			function insertBreakIfNeed(initialText, symbolWidth, availableWidth, additionalWidth) {
				var result = '';
				if (initialText.length * symbolWidth + (additionalWidth || 0) > availableWidth) {
					var words = initialText.split(' ');
					var currentLine = '';
					for (var i = 0; i < words.length; i++) {
						var endWord = i == words.length - 1;
						var word = words[i];

						var hasBr = word.indexOf('<br/>') > -1;
						if (hasBr)
							word = word.replace('<br/>', '');

						var needBr = (hasBr && result.indexOf('<br/>') == -1) || ((currentLine + word).length * symbolWidth) > availableWidth;
						if (needBr) {
							result += '<nobr>' + currentLine + '</nobr><br/>';
							currentLine = '';
						}
						currentLine += (word + ' ');
						if (endWord) {
							if (currentLine.length * symbolWidth + (additionalWidth || 0) > availableWidth)
								currentLine += '<br/>';
							result += currentLine;
						}
					}
					return result;
				} else {
					return '<nobr>' + initialText + ' </nobr>';
				}
			}

			function setMainImage(index) {
				var itemData = data.body.photos[index];

				loadImageAndFadeOut(
					itemData.imageUrl,
					MediaSyndicationWidget.jQuery(container).find('.imageSection .photoPageUrl img'),
					function (image) {
						var imageContainer = MediaSyndicationWidget.jQuery(container).find('.imageSection');
						var size = adjustImageSize(image, imageContainer.width(), imageContainer.height());

						imageContainer
						.find('.photoPageUrl').attr(getLinkAttrs(itemData.photoPageUrl)).end()
						.find('.photoPageUrl img')
							.attr('src', image.src)
							.width(size.width)
							.height(size.height)
							.css('marginTop', (imageContainer.height() - size.height) / 2 + 'px')
							.fadeIn(animationDuration);
					}
				);
			}

			function showEndScreen() {
				var endScreen = MediaSyndicationWidget.jQuery(container).find('.endScreen');
				var mainImg = MediaSyndicationWidget.jQuery(container).find('.imageSection .photoPageUrl img');

				loadImageAndFadeOut(
					data.body.account.accountProfileImageUrl,
					MediaSyndicationWidget.jQuery(container).find('.imageSection .photoPageUrl img'),
					function (image) {
						var img = endScreen.find('img');
						var size = adjustImageSize(image, parseInt(img.css('maxWidth')), parseInt(img.css('maxHeight')));

						endScreen
							.find('table').height(MediaSyndicationWidget.jQuery(container).find('.imageSection').height()).end()
							.find('a').attr(getLinkAttrs(data.body.account.homepageUrl)).end()
							.find('img').attr('src', data.body.account.accountProfileImageUrl).width(size.width).height(size.height).end()
							.fadeIn(animationDuration);

						var isSidebarView = MediaSyndicationWidget.jQuery(container).find('.sidebarView').length == 1;
						var seeMoreAvailableWidth = MediaSyndicationWidget.jQuery(container).find('.imageSection').width() -
							(isSidebarView ? 0 : endScreen.find('img').width() - parseInt(endScreen.find('.seeMore').css('paddingLeft')));
						var startText = isSidebarView ? 'More ' : 'See more ';
						var seeMoreHtml = insertBreakIfNeed(startText + data.body.account.displayName + ' <br/>photos and videos', isSidebarView ? 8.5 : 12, seeMoreAvailableWidth, isSidebarView ? 95 : 125);
						if (seeMoreHtml.indexOf('<br/>') == -1)
							seeMoreHtml = startText + data.body.account.displayName + '<br/>photos and videos ';
						endScreen.find('.seeMore a').html(seeMoreHtml + '<nobr>on WhoSay &raquo;</nobr>');
					}
				);
			}

			function selectImage(index) {
				var imageList = MediaSyndicationWidget.jQuery(container).find('.imageList ol');
				var imageListLength = imageList.find('li').length;
				if (index < 0 || imageListLength <= index)
					return;

				imageList.find('li:eq(' + currentIndex + ')').removeClass('selectedImage');

				var li = imageList.find('li:eq(' + index + ')').addClass('selectedImage');
				setDescription(index);

				var availabelResults = Math.min(Math.max(3, settings.availableResults || defaultAvailableResults), imageListLength);
				var endScreen = MediaSyndicationWidget.jQuery(container).find('.endScreen');
				if (index < availabelResults) {
					if (endScreen.css('display') != 'none') {
						endScreen.fadeOut(animationDuration, function () {
							setTimeout(function () { setMainImage(index); }, 0);
						});
					} else {
						setMainImage(index);
					}
				} else if (endScreen.css('display') == 'none') {
					showEndScreen();
				}

				currentIndex = index;
			}

			function getItemDimesions() {
				var firstElement = MediaSyndicationWidget.jQuery(container).find('.imageList ol li:eq(0)');
				return {
					width: firstElement.width(),
					fullWidth: firstElement.width() + parseInt(firstElement.css('marginRight'))
				}
			}

			function moveArrow(animate) {
				var imageArrow = MediaSyndicationWidget.jQuery(container).find('.imageListContainer .imageArrow').show();
				if (imageArrow.length > 0) {
					var arrowWidth = 9;
					var itemDimesions = getItemDimesions();
					var marginLeft = (itemDimesions.fullWidth * (currentIndex - startIndex) + itemDimesions.width / 2 - arrowWidth) + 'px';
					if (animate)
						imageArrow.animate({ marginLeft: marginLeft }, animationDuration);
					else
						imageArrow.css('marginLeft', marginLeft);
				}
			}

			function selectorPagerClick(step, e) {
				if (e) e.preventDefault();

				var imageList = MediaSyndicationWidget.jQuery(container).find('.imageList ol');

				startIndex = Math.max(Math.min(startIndex + step, imageList.find('li').length - visibleThumbnails), 0);

				var itemDimesions = getItemDimesions();
				imageList.animate({ marginLeft: -itemDimesions.fullWidth * startIndex }, animationDuration);
				moveArrow(true);

				MediaSyndicationWidget.jQuery.each(imageList.find('img').slice(startIndex, startIndex + visibleThumbnails), function () {
					if (!MediaSyndicationWidget.jQuery(this).attr('src'))
						MediaSyndicationWidget.jQuery(this).attr('src', MediaSyndicationWidget.jQuery(this).data('src'));
				});
			}

			function topPagerClick(next, e) {
				if (e) e.preventDefault();

				selectImage(currentIndex + (next ? 1 : -1));

				var step = next ? currentIndex - startIndex - visibleThumbnails + 1 : currentIndex - startIndex;
				if (startIndex > currentIndex || startIndex < currentIndex - visibleThumbnails + 1)
					selectorPagerClick(step);
				else
					moveArrow();
			}

			function checkSettingValue(settingName, possibleValues) {
				var defaultValue = possibleValues[0];
				var value = (settings[settingName] || defaultValue).toLowerCase();
				for (var i = 0; i < possibleValues.length; i++) {
					if (value === possibleValues[i])
						return value;
				}
				trace(settingName + ' has not available value. ' + settingName + ' has set to "' + defaultValue + '"');
				return defaultValue;
			}

			function getMoreOnWhoSay(displayName, viewName) {
				var initialText = 'More ' + data.body.account.displayName;
				var onWhoSayLength = 74;
				var availableWidth = (viewName == 'sidebar' ? MediaSyndicationWidget.jQuery(container).find('.footerSection').width()
					: (MediaSyndicationWidget.jQuery(container).find('.footerSection').width() - MediaSyndicationWidget.jQuery(container).find('.imageSelector').width()))
					- MediaSyndicationWidget.jQuery(container).find('.moreOnWhoSay .linkIcon').width();

				var result = insertBreakIfNeed(initialText, 7.5, availableWidth, onWhoSayLength);
				return result + (result.indexOf('<br/>') == -1 ? ' ' : '') + '<nobr>on WhoSay <span class="endArrow">&#9658;</span></nobr>';
			}

			function onDataReceived(response) {
				data = response;

				if (data.header.status == 'success') {
					var format = checkSettingValue('format', ['rectangular', 'square']);
					var viewName = checkSettingValue('view', ['main', 'sidebar']);

					if (settings.availableResults) {
						if (settings.availableResults < defaultAvailableResults)
							trace('availabeResults cannot be less than ' + defaultAvailableResults);
						if (settings.availableResults > (settings.maxResults || defaultMaxResults))
							trace('availabeResults cannot be more than maxResults');
					}

					MediaSyndicationWidget.jQuery(container)
						.html(markup[viewName])
						.find('.mainTitle').html(settings.title || ('<b>' + data.body.account.displayName + '\'s</b> Latest')).end()
						.find('.headerSection .prevButton a').click(function (e) { topPagerClick(false, e); }).end()
						.find('.headerSection .nextButton a').click(function (e) { topPagerClick(true, e); }).end()
						.find('.imageSelector .prevButton a').click(function (e) { selectorPagerClick(-3, e); }).end()
						.find('.imageSelector .nextButton a').click(function (e) { selectorPagerClick(3, e); }).end()
						.find('.moreOnWhoSay .moreLink').attr(getLinkAttrs(data.body.account.homepageUrl)).end();


					var width = MediaSyndicationWidget.jQuery(container).find('.' + viewName + 'View').width();
					MediaSyndicationWidget.jQuery(container).find('.imageSection').height(width * (format == 'square' ? 1 : 3 / 4));

					if (viewName == 'sidebar' && width < 255 || viewName == 'main' && width < 550)
						MediaSyndicationWidget.jQuery(container).find('.innerContainer').addClass('smallWidth');

					var imageList = MediaSyndicationWidget.jQuery(container).find('.imageList ol');
					MediaSyndicationWidget.jQuery.each(data.body.photos || [], function (i, itemData) {
						imageList.append(
							MediaSyndicationWidget.jQuery('<li>')
								.click(function () { selectImage(i); moveArrow(); })
								.html('<a><img /></a><div class="imageFrame"></div>')
								.find('a').attr('href', itemData.photoPageUrl).click(function (e) { e.preventDefault(); }).end()
								.find('img')[i < visibleThumbnails ? 'attr' : 'data']('src', itemData.thumbnailUrl).end()
						);
					});

					imageList.find('li:eq(0)').click();

					var moreOnWhoSay = getMoreOnWhoSay(data.body.account.displayName, viewName);
					MediaSyndicationWidget.jQuery(container).find('.moreOnWhoSay .linkText')
						.html(moreOnWhoSay)
						.toggleClass('twoLinesLinkText', moreOnWhoSay.indexOf('<br/>') > -1);
				} else {
					var errorMessage = 'Data loading error';
					if (data.messages instanceof Array) {
						errorMessage += ': ';
						MediaSyndicationWidget.jQuery.each(data.messages, function () {
							errorMessage += '{ ';
							var pairs = [];
							for (var prop in this) {
								if (this.hasOwnProperty(prop))
									pairs.push(prop + ':' + this[prop]);
							}
							errorMessage += pairs.join(', ') + ' }';
						});
					}
					trace(errorMessage);
				}
			}

			if (!settings.vanityRoot) {
				trace('vanityRoot is not defined');
				return;
			}

			if (!prepareContainer())
				return;

			includeCss();

			this.loadJQuery(function () {
				MediaSyndicationWidget.jQuery.ajax({
					url: serverUrl + '/public/getRecentPhotos/001',
					dataType: 'jsonp',
					data: { vanityRoot: settings.vanityRoot, maxResults: settings.maxResults || defaultMaxResults },
					jsonp: 'jsonpCallback',
					success: onDataReceived
				});
			});
		},
		loadJQuery: function (callback) {
			if (!!MediaSyndicationWidget.jQuery) {
				if (MediaSyndicationWidget.jQuery.isFunction(callback))
					callback();
			} else if (typeof jQuery != 'undefined' && typeof jQuery.Deferred != 'undefined') {
				MediaSyndicationWidget.jQuery = jQuery;
				if (MediaSyndicationWidget.jQuery.isFunction(callback))
					callback();
			} else {
				jQueryCallbacks.push(callback);

				if (jQueryCallbacks.length == 1) {
					var script = document.createElement("script");
					script.async = 'async';
					script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js';

					script.onload = script.onreadystatechange = function () {
						if (!script.readyState || /loaded|complete/.test(script.readyState)) {
							script.onload = script.onreadystatechange = null;
							if (head && script.parentNode)
								head.removeChild(script);
							script = undefined;
							
							MediaSyndicationWidget.jQuery = jQuery.noConflict(true);
							MediaSyndicationWidget.jQuery.each(jQueryCallbacks, function (i, l) {
								if (MediaSyndicationWidget.jQuery.isFunction(l))
									l();
							});

							jQueryCallbacks = [];
						}
					};

					var head = document.head || document.getElementsByTagName('head')[0] || document.documentElement;
					head.insertBefore(script, head.firstChild);
				}
			}
		}
	}
})();

MediaSyndicationWidget.jQuery = null;
MediaSyndicationWidget.loadJQuery();
