$(document).ready(function(){
	$('#find-out').click(function(){
		var username = $('#username').val();
		twitter.getUser(username);
	});
	$('#query-twitter').submit(function () {
		var username = $('#username').val();
		twitter.getUser(username);
		return false;
	});
});

var twitter = {
    username: '',
    tweets: [],
    userProfile : {},
    tweetsToFetch: null,
    duplicates: {},
    errors: 0,
    errorChecker: null,
    stillLoading: null,
    errorFlag: false,
    errorInterval: 2000,
    getUser: function (username) {
        that = this;
        this.username = username;

        // Reset previous use
        $('#tweet-list').children().empty();
        this.tweets = [];
        $('#explanation').remove();
        $('#results').remove();
        
        $('#security').fadeOut();
        setProgressBar(5); // Start out with 5%
        setProgressDetail("Getting user data from Twitter...");
    	$.getJSON('http://twitter.com/users/show/' + username + '.json?callback=?', function(rsp) {
            setProgressBar(10); // Move to 10%
            setProgressDetail("Received user data from Twitter...");
    	    that.userProfile = rsp;
    	    that.displayUserProfile();
            that.tweetsToFetch = rsp.statuses_count;
            if (rsp.statuses_count >= 3200) {
                var yesno = '<h3>I don\'t know.</h3>';
                var msg = rsp.name + ' has more than 3200 tweets. The Twitter API doesn\'t allow access to more than 3200 tweets, so I can\'t count them.';
                $('#status').children().fadeOut().parent().append('<div id="results">' + yesno + '<p>' + msg + '</p></div>');
            } else {
    	        that.loadNextTweets();
            }
    	});
    },
    
    // Detect errors loading JSONP, which may indicate that Twitter is
    // over capacity
    checkTwitterErrors: function() {        
        if ($('script[src^=http://twitter.com/]').length > 0) {
            // A script from Twitter is currently loaded on the page
            // If there is no error, it should be removed by jQuery once it loads.
            // If there has been an error, it will persist so we set a flag and check
            // again in a few ms.
            var src = $('script[src^=http://twitter.com/]').attr('src');
            
            // Confirming a previously detected error
            if (twitter.errorFlag == src) {
                if (twitter.stillLoading === false) {
                    twitter.errors++;
                    twitter.errorFlag = false;
                    var retry = confirm("There was an error loading data from Twitter. The service may be overcapacity or experiencing delays.\n\nWould you like to retry?");
                    if (retry) {
                        twitter.loadNextTweets();
                        twitter.errorChecker = null;
                    }
                } else {
                    console.log("Request to Twitter is still loading. Checking again for error in 1 second...");
                    twitter.errorChecker = setTimeout(function() { twitter.checkTwitterErrors(); }, 1000);
                }
            } else {
                console.log("Possible error detected. Checking again in 1 second...");
                twitter.stillLoading = true;
                $('script[src^=http://twitter.com/]').load(function() { twitter.stillLoading = false; });
                twitter.errorFlag = $('script[src^=http://twitter.com/]').attr('src');
                twitter.errorChecker = setTimeout(function() { twitter.checkTwitterErrors(); }, 1000);
            }
        } else {
            // No errors detected. Continue error check until all tweets have been fetched
            if (twitter.tweetsToFetch > 0) {
                console.log("No errors. Checking again in 2 seconds.");
                twitter.errorChecker = setTimeout(function() { twitter.checkTwitterErrors(); }, twitter.errorInterval);
            }
        }
    },
    
    loadNextTweets: function () {
        var that = this; // For inner function access to outer function's 'this'

        if (!twitter.errorChecker) {
            twitter.errorChecker = setTimeout(function() { twitter.checkTwitterErrors(); }, twitter.errorInterval);
        }

        if (this.tweetsToFetch == null) {
            $('#status').append("No tweets to fetch. [null]");
        } else {
            var currentPage = Math.round((this.userProfile.statuses_count - this.tweetsToFetch) / 200 + 1);
            setProgressDetail("Getting page " + currentPage + " of your tweets...");
    	    $.getJSON('http://twitter.com/statuses/user_timeline/' + this.username + '.json?count=200&page=' + currentPage  + '&callback=?', function(rsp) {
                var startIndex = that.tweets.length;
                for (var i=0; i < rsp.length; i++) {
                    if (!that.duplicates[rsp[i].id]) {
                        that.tweets.push(rsp[i]);
                        that.duplicates[rsp[i].id] = true;
                    } else {
                        // console.log("Skipping duplicate tweet...");
                    }
                };
                
    	        displayTweets(that.tweets.slice(startIndex));
    	        // console.log("tweetsToFetch: " + that.tweetsToFetch);
    	        // If the response contained more tweets than the number left to fetch,
    	        // then we're done
                if (rsp.length >= that.tweetsToFetch) {
    	            that.tweetsToFetch = 0;
    	            setProgressBar(100);
    	            that.tweetAnalysis();
    	        } else {
    	            that.tweetsToFetch -= rsp.length;
    	            setProgressBar(((that.userProfile.statuses_count - that.tweetsToFetch) / that.userProfile.statuses_count) * 100 * 0.9 + 10);
    	            setProgressDetail("Loaded page " + currentPage + " of your tweets...");
    	        }
                // console.log("tweetsToFetch: " + that.tweetsToFetch);
    	        // Run this function again in 1.5 seconds (to comply with Twitter API rate limiting)
    	        if (that.tweetsToFetch > 0) {
    	            setTimeout(function() { that.loadNextTweets();}, 1000);
    	        }
    	    });
        }
    },

    tweetAnalysis: function () {
        // http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-user_timeline
        // (Note the the number of statuses returned may be smaller than the
        // requested count as retweets are stripped out of the result set for
        // backwards compatibility.)
        var yesno = '';
        var msg = '';
        var tweetCountDiff = this.userProfile.statuses_count - this.tweets.length;
        if (tweetCountDiff > 0) {
            yesno = '<h3>Maybe.</h3>';
            msg = 'Your user profile says that you have posted ' + this.userProfile.statuses_count + ' tweets, but ' +
            'there are only ' + this.tweets.length + ' tweets in your user timeline. You\'re missing ' + 
            tweetCountDiff + ' status updates.<br><em>Note: this check does not include tweets made with the new retweet API. Your count will be off by the number of retweets you have made.</em>' + 
            ' <a href="http://twitter.com/home?status=@twitter+lost+' + tweetCountDiff + '+of+my+tweets.+Are+you+missing+any?+http%3a%2f%2fbit.ly%2fpFbEM">Post to Twitter &rarr;</a>';
        } else {
            yesno = '<h3>No.</h3>';
            msg = 'Your user profile says that you have posted ' + this.userProfile.statuses_count + ' tweets and ' +
            'there are ' + this.tweets.length + ' tweets in your user timeline. You\'re not missing anything!' +
            ' (Check &#8216;em out below if you don&#8217;t believe me.)' + 
            ' <a href="http://twitter.com/home?status=I+have+all+of+my+tweets.+Do+you+have+yours?+http%3a%2f%2fbit.ly%2fpFbEM">Post to Twitter &rarr;</a>';
        }
        $('#status').children().fadeOut().parent().append('<div id="results">' + yesno + '<p>' + msg + '</p></div>');
    },
    
    displayUserProfile: function () {
        var profile = '<img class="profile-photo" src="<profile_image_url>" alt="<screen_name> profile photo"> <h3><a href="http://twitter.com/<screen_name>"><name> / <screen_name></a></h3>';
        profile = profile.replace(/<screen_name>/g, this.userProfile.screen_name).
                    replace(/<name>/g, this.userProfile.name).
                    replace(/<profile_image_url>/g, this.userProfile.profile_image_url);
        $('#user-profile').html(profile);
    }
};

function setProgressBar(val) {
    $('#progress-bar:not(:visible)').fadeIn();
    if ($('#progress-bar div').length == 0) {
        // Add inner bar that moves
        $('#progress-bar').append('<div style="width: 0"> </div>');
    }
    // Check to see if val needs to be multipled to be a percent value
    if (val <= 1) {
        val *= 100;
    }
    $('#progress-bar div').animate({width: (val + "%")}, {duration: 250});
}

function setProgressDetail(msg) {
    $('#progress-detail:not(:visible)').fadeIn();
    $('#progress-detail').html(msg);
}

function displayTweets (rsp) {
	if (typeof(rsp) == 'undefined') {
	    // Post error message
        $('#results').append('<p>Response from Twitter was undefined.</p>');
	} else {
	   for (var i=0; i < rsp.length; i++) {
	       	$('#tweets').append('<li>' + rsp[i]['text'] + ' <span class="permalink"><a href="http://twitter.com/' + rsp[i].user.screen_name + '/statuses/' + rsp[i]['id'] + '">' + formatDate(rsp[i]['created_at']) + '</a></span></li>');
	   };
	}
}

function formatDate (strDate) {
    var months = ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.'];
    var d = new Date();
    var currentYear = d.getYear();
    d.setTime(Date.parse(strDate));
    // Hard-coded format here is '3:45PM Jan. 1'
    var hours = (d.getHours() > 12 ? d.getHours() - 12 : d.getHours());
    if (hours == 0) { hours = 12; }
    var meridian = (d.getHours() > 12 ? 'pm' : 'am');
    var minutes = d.getMinutes();
    var year = d.getYear == currentYear ? '' : ', ' + (d.getYear() + 1900);
    if (minutes < 10) { minutes = '0' + minutes; }
    return hours + ':' + minutes + meridian + ' ' + months[d.getMonth()] + ' ' + (d.getDate() + 1) + year;
}