window.twitterList = function() {
	'use strict';

	var _accountName;
	var _accountNameEncrypted;
	var	_retweet;
	var _replies;
	var	_num;
	var	_uniqueID;
	var _feedStyle;
	var _head;

	var getAccountName  		= function() { return _accountName; };
	var getAccountNameEncrypted = function() { return _accountNameEncrypted; };
	var getRetweet 				= function() { return _retweet; };
	var getReplies 				= function() { return _replies; };
	var getNum 					= function() { return _num; };
	var getUniqueID 			= function() { return _uniqueID; };
	var getFeedStyle 			= function() { return _feedStyle; };


	var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
	var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thurs', 'Fri', 'Sat'];

	var monthNumber = function (name){
		var i;
		for(i=0; i<months.length; i++){
			if (months[i] == name){
				return i;
			}
		}
	};

	var id = 0, global = this;

	var pgetJSON = function(url, callback) {
		var script = document.createElement('script'), token = '__jsonp' + id;

		// callback should be a global function
		global[token] = callback;

		// url should have "?" parameter which is to be replaced with a global callback name
		script.src = url.replace(/\?(&|$)/, '__jsonp' + id + '$1');

		// clean up on load: remove script tag, null script variable and delete global callback function
		script.onload = function() {
			script.remove();
			script = null;
			delete global[token];
		};
		_head.appendChild(script);

		// callback name should be unique
		id++;
	};

	// outputs the date returned by the twitter api in the format described in SBTWO-5087
	var parseTwitterDate = function (twitterDate) {

		// manually decompose twitters evil date format as ie cannot parse directly using new Date()
		var dateArray = twitterDate.split(" ");
		var timeArray = dateArray[3].split(":");

		var date = new Date(dateArray[5], monthNumber(dateArray[1]), dateArray[2], timeArray[0], timeArray[1], timeArray[2], 0);
        // SBTWO-6743 otherwise tweets during DST are displayed an hour early
        date.setMinutes(date.getMinutes() - date.getTimezoneOffset());

        var today = new Date();

		var dateSuffix = 'th';
		var dateNum = date.getDate();
		if(dateNum != 11 && dateNum != 12 && dateNum != 13) {
			if(dateNum > 9) { dateNum = dateNum % 10; }
			if (dateNum == 1) { dateSuffix = 'st'; }
			if (dateNum == 2) { dateSuffix = 'nd'; }
			if (dateNum == 3) { dateSuffix = 'rd'; }
		}

		var am = true;
		var hours = date.getHours();
		var minutes = date.getMinutes();
		minutes = ( minutes < 10 ? "0" : "" ) + minutes; // pad minutes with leading zeroes

		if (hours > 12) {
			am = false;
			hours -= 12;
		} else if(hours == 12) {
			am = false;
		} else if(hours == 0) {
			hours = 12;
		}
		var timeSuffix = (am) ? "am" : "pm";

		// check to see if the post was today or yesterday - normalize time we are only interested in date;
		today.setHours(0,0,0,0);
		date.setHours(0,0,0,0);
		var daysAgo=(Math.floor((today-date)/(1000*60*60*24)));
		var dateString;
		if (daysAgo == 0) {
			dateString="Today";
		} else if (daysAgo == 1) {
			dateString="Yesterday";
		} else {
			dateString=days[date.getDay()]+" "+date.getDate()+dateSuffix+" "+months[date.getMonth()]+" "+date.getFullYear();
		}
		return dateString+", "+hours+":"+minutes+timeSuffix;
	};

	// retweet 			do you want to see retweets? 		0 or 1
	// num 				number of tweets to return			0 - 20-ish
	// accountName 		twitter account name 				string, no at symbol
	// uniqueID			ID of the div we're working in		string
	// feedStyle
	var init = function(accountName, retweet, num, uniqueID, feedStyle, accountNameEncrypted, replies) {
		_accountName = accountName;
		_retweet = retweet;
		_num = num;
		_uniqueID = uniqueID;
		_feedStyle = feedStyle;
		_accountNameEncrypted = accountNameEncrypted;
		_replies = replies;

		if(typeof window.twitterLoaded === 'undefined' || window.twitterLoaded[uniqueID] !== true) {
			jQueryLoadTwitter();
			if(typeof window.twitterLoaded === 'undefined') {
				window.twitterLoaded = [];
			}
			window.twitterLoaded[uniqueID] = true;
		}
	};

	var mapBy = function(array, keyFn) {
		var result = {};
		jQuery.each(array || [], function(i, obj) {
			result[keyFn(obj)] = obj;
		});
		return result;
	};

	var transformItem = function (item) {
		var htmlString = item.text;
		if(item.entities) {
			/** @namespace item.entities.hashtags */
			var uniqueHashtags = mapBy(item.entities.hashtags, function(o) { return o.text; });
			var uniqueUrls = mapBy(item.entities.urls, function(o) { return o.url; });
			var uniqueMentions = mapBy(item.entities.user_mentions, function(o) { return o.screen_name; });


			jQuery.each(uniqueHashtags, function (i, obj) {
				htmlString = htmlString.replace(
					new RegExp("#" + obj.text,"g"),
						"<a target='_blank' title='Search for " + obj.text + " on X' href='http://www.twitter.com/search?q=" + obj.text + "'>#" + obj.text + "</a>"
				)
			});

			jQuery.each(uniqueUrls, function (i, obj) {
				htmlString = htmlString.replace(
					new RegExp(obj.url,"g"),
						"<a target='_blank' title='Link opens in a new window' href='" + obj.url + "'>" + obj.url + "</a>"
				)
			});

			// Match a non-username char or EOF at the end, so we don't match
			// usernames that start with another username. (SBTWO-7402)
			var USERNAME_END = "([^a-z0-9_]|$)";

			jQuery.each(uniqueMentions, function (i, obj) {
				htmlString = htmlString.replace(
					new RegExp("@" + obj.screen_name + USERNAME_END,"ig"),
						"<a target='_blank' title='Read @" + obj.screen_name +"&#39;s tweets on X' href='http://www.twitter.com/" + obj.screen_name + "'>@" + obj.screen_name + "</a>$1"
				)
			});
		}

		var datePosted = parseTwitterDate(item.created_at);
		htmlString = '<div class="tweet"><p class="tweet-text">' + htmlString + "</p>" +
			'<span class="date-posted"><a href="https://twitter.com/' + getAccountName() + '/statuses/' + item.id_str + '" title="Read this tweet on X">' + datePosted+'</a></span>';

		if (getFeedStyle() != "plaintext") {
			htmlString = htmlString + '<span class="tweet-actions">' +
				'<a href="https://twitter.com/intent/tweet?in_reply_to=' + item.id_str + '" class="tweet-reply"><i class="fa fa-fw fa-reply"></i><span class="action">Reply</span></a>' +
				'<a href="https://twitter.com/intent/retweet?tweet_id=' + item.id_str + '" class="tweet-retweet"><i class="fa fa-fw fa-retweet"></i><span class="action">Retweet</span></a>' +
				'<a href="https://twitter.com/intent/favorite?tweet_id='+ item.id_str + '" class="tweet-fav"><i class="fa fa-fw fa-star-o"></i><span class="action">Favorite</span></a>'+
				'</span>';
		}

		htmlString += '</div>';

		return htmlString;
	};

	var jQueryLoadTwitter = function() {
		if (!getAccountNameEncrypted()) {
			if (typeof(console) !== 'undefined' && typeof(console.error) === 'function') {
				console.error("Can't call Twitter API without encrypted account name!");
			}
			return;
		}

		var url = '/sitebuilder2/api/twitter_timeline.json?account=' + encodeURIComponent(getAccountNameEncrypted());
		url += '&count='+(getNum()+20)+'&include_entities=true&include_rts=' +getRetweet()+ '&exclude_replies=' +(getReplies() ? 'false' : 'true') + '&callback=?';

		jQuery.getJSON(url, function (data) {
			var count = 0;

			jQuery.each(data, function (index, item) {
				if (count < getNum()) {
					var htmlString = transformItem(item);
					jQuery('#twitter-container-'+ getUniqueID()).append(htmlString);
					count = count + 1;
				}
			});

			var user = data[0].user;
			var avatar = jQuery('<img />').attr("src",  user.profile_image_url_https || user.profile_image_url).attr("alt", user.name);
			jQuery(avatar).appendTo('#twitter-container-' + getUniqueID() + ' .twitter-image-link');

			jQuery('#twitter-container-' + getUniqueID() + ' .twitter-name').prepend(data[0].user.name);
		});

	};

	return {
		init: init,
		pgetJSON: pgetJSON,
		_transformItem: transformItem,
		_parseDate: parseTwitterDate
	}

};
