// current settings
var timeSpanInfo = getStartDayInfo('12/2011', '2/2012');
var settings = {
	days: timeSpanInfo.days,
	startday: timeSpanInfo.startday,
	'words': 20,
	'postToWall': true,
	'friendID': globals.userID
};

var statuses,
	cloud,
	reblogs,
	reblogCount,
	postData;
var firstPostDateline = globals.servertime.getTime()/1000;
var avatar = '';
var lastPost = 0;
var postCount = null;
var posts = [];
var remaining_hits = 150;

$(function(){
	// embed the generator even if we dont need it
	var flashvars = {
	};
	var params = {
		menu: 'false',
		allowscriptaccess: 'always',
		wmode: 'transparent'
	};
	var attributes = {
		id: 'cloudGenerator',
		name: 'cloudGenerator'
	};
	swfobject.embedSWF(globals.cdn + 'media/v' + globals.version + '/cloudGenerator.swf', 'cloudGenerator', 1, 1, '9.0.0','expressInstall.swf', flashvars, params, attributes);


	$.jsonp({
		url: 'http://api.twitter.com/1/account/rate_limit_status.json?callback=?',
		success: function (json) { remaining_hits = json.remaining_hits; }
	});

	if (globals.userID > 0) {

		$("#days-header").html('look at tweets between <span>' +  getDateString((globals.servertime.getTime()/1000) - (86400 * (settings.days))) + '<' + '/span> and <span>' + getDateString((globals.servertime.getTime()/1000) - (86400 * settings.startday)) + '<' + '/span>');
		$('#preview .example .title').text('This is a Tweet Cloud I generated from my tweets between ' +  getDateString((globals.servertime.getTime()/1000) - (86400 * (settings.days))) + ' and ' + getDateString((globals.servertime.getTime()/1000) - (86400 * settings.startday)) + ' containing my top ' + settings.words + ' used words.');

		// postToWall checkbox bindings
		$('#postToWall').bind('change', function(){
			settings.postToWall = $(this).is(':checked');
			
			if (settings.postToWall) {
				//if (settings.postTopReblogs) $('#postTopReblogs').attr('checked','checked');
				$('#preview').css('color', '#3f3f3f');
				$('#preview .features').slideDown();
			} else {
				//$('#postTopReblogs').removeAttr('checked','checked');
				$('#preview').css('color', '#cccccc');
				$('#preview .features').slideUp();
			}
		});
		/*
		$('#postTopReblogs').bind('change', function(){
			settings.postTopReblogs = $(this).is(':checked');
		});
		*/

		$('#start').val('12/2011');
		$('#end').val('2/2012');
		
		$('select').selectToUISlider({
			labels: 7,
			range: true,
			slide: function (e, ui) {
				var fieldset = $(e.target).parent();
				
				var startString = $('select:eq(0) option:eq(' + ui.values[0] + ')', fieldset).val();
				var endString = $('select:eq(0) option:eq(' + ui.values[1] + ')', fieldset).val();
				
				var timeSpanInfo = getStartDayInfo(startString, endString);
				settings.days = timeSpanInfo.days;
				settings.startday = timeSpanInfo.startday;
				
				$("#days-header").html('look at tweets between <span>' +  getDateString((globals.servertime.getTime()/1000) - (86400 * (settings.days))) + '<' + '/span> and <span>' + getDateString((globals.servertime.getTime()/1000) - (86400 * settings.startday)) + '<' + '/span>');
		
				$('#preview .example .title').text('This is a Tweet Cloud I generated from my tweets between ' +  getDateString((globals.servertime.getTime()/1000) - (86400 * (settings.days))) + ' and ' + getDateString((globals.servertime.getTime()/1000) - (86400 * settings.startday)) + ' containing my top ' + settings.words + ' used words.');
		
				if (settings.days > 100) {
					$('#longwait-notice').fadeIn();
				} else {
					$('#longwait-notice').fadeOut();
				}
			}
		});
		
		// days-slider bindings
		$('#words-slider').slider({
			min: 2,
			max: 90,
			range: "min",
			value: settings.words,
			slide: function(event, ui) {
				settings.words = ui.value;

				if (ui.value > 1) {
					$("#words-header").html('show the top <span>' + settings.words + '<' + '/span> most used words in my cloud');
				} else {
					$("#words-header").html('show only the top used word in my cloud');
				}

				$('#preview .example .title').text('This is a Tweet Cloud I generated from my tweets between ' +  getDateString((globals.servertime.getTime()/1000) - (86400 * (settings.days))) + ' and ' + getDateString((globals.servertime.getTime()/1000) - (86400 * settings.startday)) + ' containing my top ' + settings.words + ' used words.');
			}
		});
		
		
		$('#create-cloud-form .submit-orange').bind('click', function(){
			$('#create-cloud-form .submit-orange').attr('disabled', 'true');
			$('#create-cloud-form .submit-orange').val('loading...');

			// tracking
			if (settings.postToWall) {
				_gaq.push(['_trackPageview', 'create_cloud_and_post']);
			} else {
				_gaq.push(['_trackPageview', 'create_cloud']);
			}


			addBlogPosts();
		});
	}
	autoPlaceFooter();
});

var setCloudImage = function (imageBase64) {

	if (settings.postToWall || typeof globals.problem != 'undefined') {
		if (typeof globals.problem != 'undefined') postData.problem = true;
		postData.imageBase64 = imageBase64;
		
		// create image
		$.ajax({
			type: 'POST',
			url:  'ajax.php',
			dataType: 'json',
			settings: settings.days,
			
			data: postData,
			
			success: function(json){
				switch ( json.code ) {
					case 1:
						window.location.href = globals.basedomain + json.userid + '/' + json.cloudid; 
						break;
					case 4:
						$('#preview .example .cloud-image').remove();
						$('#preview .example').css('height','auto');
						$('#cloud').html('<img src="data:image/png;base64,'+ json.image +'" />');
						break;
					case 5:
						alert(json.error);
						break;
				}
			},
			
			beforeSend: function(){
	
			},
			
			complete: function(){
				$('#create-cloud-form .submit-orange').removeAttr('disabled');
				$('#create-cloud-form .submit-orange').val('Generate my cloud');
				$('#overfifty-notice').fadeOut();
			}
		});
	} else {
		$('#cloud').html('<img src="data:image/jpeg;base64,'+ imageBase64 +'" />');
		$('#create-cloud-form .submit-orange').removeAttr('disabled');
		$('#create-cloud-form .submit-orange').val('Generate my cloud');
		$('#overfifty-notice').fadeOut();
		
		firstPostDateline = globals.servertime.getTime()/1000;
		avatar = '';
		lastPost = 0;
		postCount = null;
		posts = [];
	}
		
	// post to wall
};





var addBlogPosts = function (json) {
	remaining_hits--;
	if (!json) {
	
		// first time its been called

		// fallback jsonp with three retries (this is horrible... but its tumblrs fault)
		
		$.jsonp({
			
			url: (globals.protected || remaining_hits <= 15 ? globals.basedomain + 'authenticated-proxy.php?' : 'http://api.twitter.com/1/statuses/user_timeline/' + globals.screen_name + '.json?') + 'count=200&include_rts=1&callback=?',
			success: addBlogPosts,
			error: function(xOptions, textStatus) {
				// retry 1
				$.jsonp({
					url: xOptions.url.replace(/callback=\?/, 'callback=' + xOptions.callback),
					success: addBlogPosts,
					error: function (xOptions, textStatus) {
						// retry 2
						$.jsonp({
							url: xOptions.url.replace(/callback=\?/, 'callback=' + xOptions.callback),
							success: addBlogPosts,
							error: function (xOptions, textStatus) {
								// retry 3
								$.jsonp({
									url: xOptions.url.replace(/callback=\?/, 'callback=' + xOptions.callback),
									success: addBlogPosts
								});
							}
						});
					}
				});
			}
		});
		
		return false;
	}
	
	if (postCount === null) {
		// first time its returned with data
	    postCount = json[0].user['statuses_count'] > 2000 ? 2000 : json[0].user['statuses_count'];
	}
	
	var oldest = (globals.servertime.getTime()/1000) - (Math.floor(settings.days)*86400);
	var youngest = (globals.servertime.getTime()/1000) - (86400 * (Math.floor(settings.startday)));

	for (post in json) {

		var dateParts = json[post].created_at.match(/(\w+) (\w+) (\d{2}) (\d{2}):(\d{2}):(\d{2}) (?:\+\d+) (\d{4})/i);
		var time = new Date(Date.parse(dateParts[2] + ' ' + dateParts[3] + ', ' + dateParts[7]));
		// GMT -7
		time.setHours(dateParts[4]  - 7);
		time.setMinutes(dateParts[5]);
		time.setSeconds(dateParts[6]);
		var created_at = Math.round(time.getTime() / 1000);

		if (created_at < oldest) {
			crawlingComplete();
			return false;
		} else if (created_at < youngest) {
			// process post, its young enough
			if (!json[post].text.match(/Just generated a Tweet Cloud/i)) posts.push(json[post].text);
		}

		
		if (json[post].user.id == parseInt(globals.userID) && (json[post].id < lastPost || (!lastPost))) lastPost = json[post].id-1;
	}
	


	if (posts.length > 50) {
		$('#overfifty-notice .count').text(posts.length);
		$('#overfifty-notice').fadeIn();
	}

	if (json.length) {
	
		// continue crawling posts
		// fallback jsonp with three retries (this is horrible... but its tumblrs fault)
		$.jsonp({
			url: (globals.protected || remaining_hits <= 15 ? globals.basedomain + 'authenticated-proxy.php?' : 'http://api.twitter.com/1/statuses/user_timeline/' + globals.screen_name + '.json?') + 'count=200&callback=?&include_rts=1&max_id=' + lastPost + '&count=200',
			success: addBlogPosts,
			error: function(xOptions, textStatus) {
				// retry 1
				$.jsonp({
					url: xOptions.url.replace(/callback=\?/, 'callback=' + xOptions.callback),
					success: addBlogPosts,
					error: function (xOptions, textStatus) {
						// retry 2
						$.jsonp({
							url: xOptions.url.replace(/callback=\?/, 'callback=' + xOptions.callback),
							success: addBlogPosts,
							error: function (xOptions, textStatus) {
								// retry 3
								$.jsonp({
									url: xOptions.url.replace(/callback=\?/, 'callback=' + xOptions.callback),
									success: addBlogPosts
								});
							}
						});
					}
				});
			}
		});
	} else {
		// we have crawled all of the users posts
		crawlingComplete();
	}
};


var blacklistedWords = {'tumblr': 1, 'about': 1, 'above': 1, 'across': 1, 'after': 1, 'again': 1, 'against': 1, 'almost': 1, 'alone': 1, 'along': 1, 'already': 1, 'also': 1, 'although': 1, 'always': 1, 'among': 1, 'another': 1, 'anybody': 1, 'anyone': 1, 'anything': 1, 'anywhere': 1, 'area': 1, 'areas': 1, 'around': 1, 'asked': 1, 'asking': 1, 'asks': 1, 'away': 1, 'back': 1, 'backed': 1, 'backing': 1, 'backs': 1, 'became': 1, 'because': 1, 'become': 1, 'becomes': 1, 'been': 1, 'before': 1, 'began': 1, 'behind': 1, 'being': 1, 'beings': 1, 'best': 1, 'better': 1, 'between': 1, 'both': 1, 'came': 1, 'cannot': 1, 'case': 1, 'cases': 1, 'certain': 1, 'certainly': 1, 'clear': 1, 'clearly': 1, 'come': 1, 'could': 1, 'differ': 1, 'different': 1, 'differently': 1, 'does': 1, 'done': 1, 'down': 1, 'down': 1, 'downed': 1, 'downing': 1, 'downs': 1, 'during': 1, 'each': 1, 'early': 1, 'either': 1, 'ended': 1, 'ending': 1, 'ends': 1, 'enough': 1, 'even': 1, 'evenly': 1, 'ever': 1, 'every': 1, 'everybody': 1, 'everyone': 1, 'everything': 1, 'everywhere': 1, 'face': 1, 'faces': 1, 'fact': 1, 'facts': 1, 'felt': 1, 'find': 1, 'finds': 1, 'first': 1, 'four': 1, 'from': 1, 'full': 1, 'fully': 1, 'further': 1, 'furthered': 1, 'furthering': 1, 'furthers': 1, 'gave': 1, 'general': 1, 'generally': 1, 'gets': 1, 'give': 1, 'given': 1, 'gives': 1, 'going': 1, 'good': 1, 'goods': 1, 'great': 1, 'greater': 1, 'greatest': 1, 'group': 1, 'grouped': 1, 'grouping': 1, 'groups': 1, 'have': 1, 'having': 1, 'here': 1, 'herself': 1, 'high': 1, 'high': 1, 'high': 1, 'higher': 1, 'highest': 1, 'himself': 1, 'however': 1, 'important': 1, 'interest': 1, 'interested': 1, 'interesting': 1, 'interests': 1, 'into': 1, 'itself': 1, 'just': 1, 'keep': 1, 'keeps': 1, 'kind': 1, 'knew': 1, 'know': 1, 'known': 1, 'knows': 1, 'large': 1, 'largely': 1, 'last': 1, 'later': 1, 'latest': 1, 'least': 1, 'less': 1, 'lets': 1, 'like': 1, 'likely': 1, 'long': 1, 'longer': 1, 'longest': 1, 'made': 1, 'make': 1, 'making': 1, 'many': 1, 'member': 1, 'members': 1, 'might': 1, 'more': 1, 'most': 1, 'mostly': 1, 'much': 1, 'must': 1, 'myself': 1, 'necessary': 1, 'need': 1, 'needed': 1, 'needing': 1, 'needs': 1, 'never': 1, 'newer': 1, 'newest': 1, 'next': 1, 'nobody': 1, 'noone': 1, 'nothing': 1, 'nowhere': 1, 'number': 1, 'numbers': 1, 'often': 1, 'older': 1, 'oldest': 1, 'once': 1, 'only': 1, 'open': 1, 'opened': 1, 'opening': 1, 'opens': 1, 'order': 1, 'ordered': 1, 'ordering': 1, 'orders': 1, 'other': 1, 'others': 1, 'over': 1, 'part': 1, 'parted': 1, 'parting': 1, 'parts': 1, 'perhaps': 1, 'place': 1, 'places': 1, 'point': 1, 'pointed': 1, 'pointing': 1, 'points': 1, 'possible': 1, 'present': 1, 'presented': 1, 'presenting': 1, 'presents': 1, 'problem': 1, 'problems': 1, 'puts': 1, 'quite': 1, 'rather': 1, 'really': 1, 'right': 1, 'right': 1, 'room': 1, 'rooms': 1, 'said': 1, 'same': 1, 'says': 1, 'second': 1, 'seconds': 1, 'seem': 1, 'seemed': 1, 'seeming': 1, 'seems': 1, 'sees': 1, 'several': 1, 'shall': 1, 'should': 1, 'show': 1, 'showed': 1, 'showing': 1, 'shows': 1, 'side': 1, 'sides': 1, 'since': 1, 'small': 1, 'smaller': 1, 'smallest': 1, 'some': 1, 'somebody': 1, 'someone': 1, 'something': 1, 'somewhere': 1, 'state': 1, 'states': 1, 'still': 1, 'still': 1, 'such': 1, 'sure': 1, 'take': 1, 'taken': 1, 'than': 1, 'that': 1, 'their': 1, 'them': 1, 'then': 1, 'there': 1, 'therefore': 1, 'these': 1, 'they': 1, 'thing': 1, 'things': 1, 'think': 1, 'thinks': 1, 'this': 1, 'those': 1, 'though': 1, 'thought': 1, 'thoughts': 1, 'three': 1, 'through': 1, 'thus': 1, 'today': 1, 'together': 1, 'took': 1, 'toward': 1, 'turn': 1, 'turned': 1, 'turning': 1, 'turns': 1, 'under': 1, 'until': 1, 'upon': 1, 'used': 1, 'uses': 1, 'very': 1, 'want': 1, 'wanted': 1, 'wanting': 1, 'wants': 1, 'ways': 1, 'well': 1, 'wells': 1, 'went': 1, 'were': 1, 'what': 1, 'when': 1, 'where': 1, 'whether': 1, 'which': 1, 'while': 1, 'whole': 1, 'whose': 1, 'will': 1, 'with': 1, 'within': 1, 'without': 1, 'work': 1, 'worked': 1, 'working': 1, 'works': 1, 'would': 1, 'year': 1, 'years': 1, 'young': 1, 'younger': 1, 'youngest': 1, 'your': 1, 'yours': 1, 'dont': 1, 'thats': 1, 'youre': 1, 
/* stupid replacemnts */
'(via': 1, 'didn': 1, 'http': 1, 'wasn': 1, 'doesn': 1,
/* auxiliary verbs */
'am': 1, 'arent': 1, 'aint': 1, 'im': 1, 'are': 1, 'arent': 1, 'aint': 1, 'be': 1, 'been': 1, 'can': 1, 'cant': 1, 'could': 1, 'couldnt': 1, 'did': 1, 'didnt': 1, 'do ': 1, 'dont': 1, 'does': 1, 'doesnt': 1, 'had': 1, 'hadnt': 1, 'has': 1, 'hasnt': 1, 'have': 1, 'havent': 1, 'ive': 1, 'is': 1, 'isnt': 1, 'may': 1, 'maynt': 1, 'might': 1, 'mightnt': 1, 'must': 1, 'mustnt': 1, 'ought': 1, 'oughtnt': 1, 'shall': 1, 'shant': 1, 'should': 1, 'shouldnt': 1, 'was': 1, 'wasnt': 1, 'were': 1, 'werent': 1, 'will': 1, 'wont': 1, 'would': 1, 'wouldnt': 1, 'shes': 1, 'hes': 1, 'she': 1, 'he': 1, 'shell': 1, 'id': 1
};

var crawlingComplete = function () {
	cloud = {};
	reblogs = {};
	reblogCount = 0;
	
	var tumblelogRegex = /[@#]([A-Za-z0-9_]+)/ig;
	//var tumblelogViaRegex = /\(via <a href="[^"]+"[^>]*>([a-z0-9-_]+)<\/a>\:?\)/gi;
	
	for (var i = 0, len = posts.length; i < len; i++) {
			var html = posts[i];
			//var original = true;
			
			while (match = tumblelogRegex.exec(html))
			{
				if (match[1] == globals.tumblelog) continue;
				if (match[1].match(/(post|photo)/i)) continue;
				
				if (typeof reblogs[match[1]] != 'undefined') {
					reblogs[match[1]]++;
				} else {
					reblogs[match[1]] = 1;
				}
				//if (original) {
				//	reblogCount++;
				//	original = false;
				//}
			}
			
			if (html.match(/RT @/ig)) reblogCount++;
			//console.log(html);
			
			html = html.replace(tumblelogRegex, '');
			//html = html.replace(tumblelogViaRegex, '');
			var textBlob = html.replace(/<\/?[^>]+(>|$)/g, '')
			.toLowerCase()
			.replace(/((ht|f)tp(s?):\/\/)(([a-z0-9]([a-z0-9]|-)*[a-z0-9]|[a-z0-9])\.)+([a-z]([a-z0-9]|-)*[a-z0-9]|[a-z])(\/([a-z0-9\.!$&'\(\)*+,;=_~:@-]|%[a-f0-9]{2})*)*(\?[a-z0-9\.!$&'\(\)*+,;=_~:@\/?-]*)?(\#[a-z0-9\.!$&'\(\)*+,;=_~:@\/?-]*)?/g, '')
			.replace(/[\ï\Í\'\(\)\:]/ig, '')
			.replace(/[^a-z0-9\-\_]+/ig, ' ')
			.replace(/  /ig, ' ')
			.replace(/ [0-9]+ /ig, '');
			
			
			var initial_words_array = textBlob.split(' ');
			var new_textBlob = textBlob;
			var popularity = {};
		
			var _i;
			for (_i in initial_words_array) {
				if (typeof popularity[initial_words_array[_i]] != 'undefined') {
					popularity[initial_words_array[_i]].count++;
					popularity[initial_words_array[_i]].points += Math.floor(10 / (popularity[initial_words_array[_i]].count+2));
				} else {
					if (initial_words_array[_i].length > 3 && typeof blacklistedWords[initial_words_array[_i]] == 'undefined') {
						popularity[initial_words_array[_i]] = {
							count: 1,
							word: initial_words_array[_i],
							points: 10
						};
					}
				}
			}
		
			var _i;
			for (_i in popularity) {
				if (typeof cloud[popularity[_i].word] != 'undefined') {
					cloud[popularity[_i].word].count += popularity[_i].count;
					cloud[popularity[_i].word].points += popularity[_i].points;
				} else {
					cloud[popularity[_i].word] = {
						count: popularity[_i].count,
						word: popularity[_i].word,
						points: popularity[_i].points
					};
				}
			}
	}
	
	var sortedArray = [];
	var i;
	for (i in cloud) {
		sortedArray.push(cloud[i]);
	}
	
	// sort array
	usort(sortedArray, function (a, b) {return (a.points > b.points) ? +1 : -1;});

	// chop the set up
	var wordsToReturn = settings.words;
	var total_words = 0;
	var total_points = 0;
	var words = [];
	for (var i = 0, len = sortedArray.length; i < len && i < wordsToReturn; i++) {
		var word = sortedArray.pop();
		words.push(word);
		total_words += word.count;
		total_points += word.points;
	}
	
	for (var i = 0, len = words.length; i < len; i++) {
		words[i].percent = words[i].points / total_points;
	};
	
	// sort reblogs
	var reblogsSortable = [];
	for (reblog in reblogs) {
		reblogsSortable.push({
			username: reblog,
			count: reblogs[reblog]
		});
	}
	usort(reblogsSortable, function (a, b) {return (a.count < b.count) ? +1 : -1;});
	reblogsSortable = reblogsSortable.slice(0,10);
	
	// create stringify object
	var stringified = {};
	stringified.words = [];
	stringified.count = [];
	stringified.percent = [];
	stringified.reblogs = [];
	
	for (var i = 0, len = words.length; i < len; i++) {
		stringified.words.push(words[i].word);
		stringified.count.push(words[i].count);
		stringified.percent.push(words[i].percent);
	}
	
	for (var i = 0, len = reblogsSortable.length; i < len; i++) {
		stringified.reblogs.push(reblogsSortable[i].username);
	}
	
	postData = {};
//	var i;
//	for (i in userInfo) postData[i] = userInfo[i];
	
	postData.method = 'create.cloud';
	postData.postToWall = settings.postToWall;
	//postData.postTopReblogs = settings.postTopReblogs;
	postData.friendID = settings.friendID;
	postData.max = settings.words;
	postData.startday = settings.startday;
	postData.days = settings.days;
	postData.words = stringified.words.join(',');
	postData.count = stringified.count.join(',');
	postData.percent = stringified.percent.join(',');
	postData.reblogs = stringified.reblogs.join(',');
	postData.totalPosts = posts.length;
	postData.totalReblogs = reblogCount;
	
	var daysRegistered = ((globals.servertime.getTime()/1000) - firstPostDateline) / 86400;
	var postsPerDay = parseInt(postCount)/daysRegistered;
	var selectionPostPerDay = posts.length/(settings.days-settings.startday);
	var postFrequencyChange = Math.ceil((selectionPostPerDay/postsPerDay)*100) - 100;

	$('#cloudGenerator')[0].createCloudPost([
		globals.name,
		globals.screen_name,
		globals.profile_picture, 			
		postData.words,
		postData.count, 
		posts.length, 
		postFrequencyChange, 
		reblogCount, 
		posts.length-reblogCount, 
		((globals.servertime.getTime()/1000) - (settings.days*86400)) * 1000, 
		((globals.servertime.getTime()/1000) - (settings.startday*86400)) * 1000
	].join('|'));
	
};

			
/*
* usort
*/
var usort = function (inputArr, sorter) { 
	var valArr = [];
	var k = '', i = 0;
 
	if (typeof sorter === 'string') {
		sorter = this[sorter];
	} else if (sorter instanceof Array) {
		sorter = this[sorter[0]][sorter[1]];
	}
	for (k in inputArr) {
		valArr.push(inputArr[k]);
		delete inputArr[k];
	}
	try {
		valArr.sort(sorter);
	} catch (e) {
		return false;
	}
	for (i = 0; i < valArr.length; i++) {
		inputArr[i] = valArr[i];
	}
 
	return true;
};


var getDateString = function (timestamp) {
    var date = new Date(timestamp * 1000);
    var monthNames = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    
    //return monthNames[date.getMonth()] + ' ' + getSuffixWithNumber(date.getDate()) + ' ' + date.getFullYear();
    return monthNames[date.getMonth()] + ' ' + date.getFullYear();
}

var getSuffixWithNumber = function ($n){
	var n=$n+'';
	var l=n.length, r=parseInt(n.substring(l-2,l)), i = n % 10;
	return $n + (((r < 11 || r > 19) && (i < 4)) ? ['th','st','nd','rd'][i] : 'th');
}

function getStartDayInfo (startString, endString) {
	var start = new Date();
	start.setMonth(parseInt(startString.split('/')[0])-1);
	start.setFullYear(parseInt(startString.split('/')[1]));
	start.setDate(1);
	start.setHours(0);
	start.setMinutes(0);
	start.setSeconds(0);
	start.setMilliseconds(0);

	var end = new Date();
	end.setMonth(parseInt(endString.split('/')[0])-1);
	end.setFullYear(parseInt(endString.split('/')[1]));
	end.setHours(0);
	end.setMinutes(0);
	end.setSeconds(0);
	end.setMilliseconds(0);
	
	var startday = (new Date().getTime() - end.getTime())/86400000;
	var days = (new Date().getTime() - start.getTime())/86400000;
	
	return {
		startday: startday,
		days: days
	};
}

