﻿/*

todo: switch to user-urls array instead of URL format, cos the live tweet stream points to party page instead of otherwise

*/

(function($) {

    // The stream mode enum
    $.tweetStreamMode = { From: 0, Mention: 1, FromAndMention: 2 };
    $.tweetStreamJoinMode = { None: 0, Auto: 1, Pronoun: 2, ScreenName: 3 };

    // some constants
    var screenNameSymbol = "SCREENNAME";

    $.fn.tweetStream = function(o) {
        var s = {
            username: "",                               // [string]   required, unless you want to display no tweets :)
            user_url: null,                             // [string]   optional, the user url, if null, default to twitter URL
            user_url_target: "_blank",                  // [string]      user url target anchor tag attribute value
            use_twitter_server: true,                   // [Boolean]  whether or not to twitter from locally
            show_user: true, 						    // [Boolean]  show user name in tweet?
            avatar_size: 32, 						    // [integer]  height and width of avatar if displayed
            count: 10,                                  // [integer]  how many tweets to display?
            intro_text: null,                           // [string]   do you want text BEFORE your your tweets?
            outro_text: null,                           // [string]   do you want text AFTER your tweets?
            join_mode: $.tweetStreamJoinMode.None,      // [string]   join mode in between date and tweet, try setting to see $.tweetStreamJoinMode
            pronoun_join_text_default: "i said,",       // [string]   auto text for non verb: "i said" bullocks
            pronoun_join_text_ed: "i",                  // [string]   auto text for past tense: "i" surfed
            pronoun_join_text_ing: "i am",              // [string]   auto tense for present tense: "i was" surfing
            pronoun_join_text_reply: "i replied to",    // [string]   auto tense for replies: "i replied to" @someone "with"
            pronoun_join_text_url: "i was looking at",  // [string]   auto tense for urls: "i was looking at" http:...

            screen_name_join_text_default: screenNameSymbol + " said,",     // [string]   auto text for non verb: "CVertex said" bullocks
            screen_name_join_text_ed: screenNameSymbol + "",                 // [string]   auto text for past tense: "CVertex" surfed
            screen_name_join_text_ing: screenNameSymbol + " is",             // [string]   auto tense for present tense: "CVertex was" surfing
            screen_name_join_text_reply: screenNameSymbol + " replied to",   // [string]   auto tense for replies: "CVertex replied to" @someone "with"
            screen_name_join_text_url: screenNameSymbol + " was looking at", // [string]   auto tense for urls: "CVertex was looking at" http:...

            user_url_format: "http://twitter.com/" + screenNameSymbol,       // [string]     screen name format for twitter profile page, e.g. "http://twitter.com/SCREENNAME"

            loading_text: null,                      // [string]   optional loading text, displayed while tweets load
            stream_mode: $.tweetStreamMode.From      // [$.tweetStreamMode] stream mode default is $.tweetStreamMode.From
        };



        // message suffix expressions
        var reply_exp = /^(@([A-Za-z0-9-_]+)) .*/i;
        var url_exp = /(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i;
        var past_tense_exp = /^((\w+ed)|just) .*/im;
        var adjective_exp = /^(\w*ing) .*/i;

        function relative_time(time_value) {
            if ($.browser.msie) { // ie's Date.parse doesn't like the timezone specifier, e.g. +1000
                time_value = time_value.replace(/\+\d{4}/, '');
            }
            var parsed_date = Date.parse(time_value);
            var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
            var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
            if (delta < 60) {
                return 'less than a minute ago';
            } else if (delta < 120) {
                return 'about a minute ago';
            } else if (delta < (45 * 60)) {
                return (parseInt(delta / 60)).toString() + ' minutes ago';
            } else if (delta < (90 * 60)) {
                return 'about an hour ago';
            } else if (delta < (24 * 60 * 60)) {
                return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
            } else if (delta < (48 * 60 * 60)) {
                return '1 day ago';
            } else {

                return (parseInt(delta / 86400)).toString() + ' days ago';
            }
        }

        function generate_user_url(settings,screenName, urlArrayIndex) {
            if (urlArrayIndex == -1 || settings.user_url.length == 0 || settings.user_url.length < urlArrayIndex) {
                return "http://twitter.com/" + screenName;
            }

            return settings.user_url[urlArrayIndex];
        }

        function generate_screen_name_join_text(settings, joinText, screenName, urlArrayIndex) {
            var user_url = generate_user_url(settings, screenName, urlArrayIndex);
            var replaceText = '<a target="' + settings.user_url_target + '" href="' + user_url + '">' + screenName + '</a>'
            return joinText.replace(screenNameSymbol, replaceText);
        }

        function generate_join_text(settings, text, screenName, urlArrayIndex) {
            var jt = '';

            switch (settings.join_mode) {
                case $.tweetStreamJoinMode.None:
                    return null;
                    break;
                case $.tweetStreamJoinMode.ScreenName:
                    if (text.match(reply_exp)) {
                        jt = generate_screen_name_join_text(settings, settings.screen_name_join_text_reply, screenName, urlArrayIndex);
                    } else if (text.match(url_exp)) {
                        jt = generate_screen_name_join_text(settings, settings.screen_name_join_text_url, screenName, urlArrayIndex);
                    } else if (text.match(past_tense_exp)) {
                        jt = generate_screen_name_join_text(settings, settings.screen_name_join_text_ed, screenName, urlArrayIndex);
                    } else if (text.match(adjective_exp)) {
                        jt = generate_screen_name_join_text(settings, settings.screen_name_join_text_ing, screenName, urlArrayIndex);
                    } else {
                        jt = generate_screen_name_join_text(settings, settings.screen_name_join_text_default, screenName, urlArrayIndex);
                    }
                    break;
                case $.tweetStreamJoinMode.Auto:
                case $.tweetStreamJoinMode.Pronoun:
                default:
                    if (text.match(reply_exp)) {
                        jt = settings.pronoun_join_text_reply;
                    } else if (text.match(url_exp)) {
                        jt = settings.pronoun_join_text_url;
                    } else if (text.match(past_tense_exp)) {
                        jt = settings.pronoun_join_text_ed;
                    } else if (text.match(adjective_exp)) {
                        jt = settings.pronoun_join_text_ing;
                    } else {
                        jt = settings.pronoun_join_text_default;
                    }
                    break;
            }
            return jt;
        }

        function generate_avatar_title(screenName) {
            return "See " + screenName;
        }

        function generate_twitter_query(mode, usernames) {
            var q = '';
            switch (mode) {
                case $.tweetStreamMode.FromAndMention:
                    q = "from:" + usernames.join('%20OR%20from:') + "%20OR%20%40" + usernames.join('%20OR%20%40');
                    break;
                case $.tweetStreamMode.Mention:
                    q = "%40" + usernames.join('%20OR%20%40');
                    break;
                case $.tweetStreamMode.From:
                default:
                    q = "from:" + usernames.join('%20OR%20from:');
                    break;
            }
            return q;
        }


        function generate_local_url(mode, usernames, count) {
            var url = "/Twitter/"
            var q = '?';
            switch (mode) {
                case $.tweetStreamMode.FromAndMention:
                    url += "FromAndMentions"
                    break;
                case $.tweetStreamMode.Mention:
                    url += "Mentions"
                    break;
                case $.tweetStreamMode.From:
                default:
                    url += "From"
                    break;
            }
            q += "screenNames=" + usernames.join("&screenNames=") + "&count=" + count;

            return url + q;
        }

        if (o) $.extend(s, o);

        return this.each(function() {
            var list = $(this);
            var intro = '<p class="tweet_intro">' + s.intro_text + '</p>'
            var outro = '<p class="tweet_outro">' + s.outro_text + '</p>'
            var loading = $('<p class="loading">' + s.loading_text + '</p>');

            s.username = $.makeArray(s.username);
            s.user_url = $.makeArray(s.user_url); // TODO: use this to get the user url
            var url = "";
            if (s.use_twitter_server) {
                url = 'http://search.twitter.com/search.json?q=' + generate_twitter_query(s.stream_mode, s.username) + '&rpp=' + s.count + '&callback=?';
            } else {
                url = generate_local_url(s.stream_mode, s.username, s.count);
            }

            if (s.loading_text) $(this).append(loading);

            $.getJSON(url, function(data) {
                if (s.loading_text) loading.remove();
                if (s.intro_text) list.before(intro);

                $.each(data.results, function(i, item) {

                    var screenNameArrayIndex = s.username.indexOf(item.from_user);

                    // generate the join text (between avatar and text)
                    var join_text = generate_join_text(s, item.text,item.from_user,screenNameArrayIndex);
                    var join = '<span class="tweet_join"> ' + join_text + ' </span>';
                    var avatarTitle = generate_avatar_title(item.from_user);

                    var user_url = generate_user_url(s, item.from_user,screenNameArrayIndex);


                    list.append('<div class="tweet">' +
                                    (s.show_user ? '<a class="avatar" target="' + s.user_url_target + '" title="' + avatarTitle + '" href="' + user_url + '"><img class="tweet_avatar" src="' + item.profile_image_url + '" height="' + s.avatar_size + '" width="' + s.avatar_size + '" alt="avatar"/></a>' : '') +
                                    ((join_text) ? join : ' ') +
                                    '<span class="message">' +
                                    item.text.replace(/(\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+)/gi, '<a target="_blank" href="$1">$1</a>').replace(/[\@]+([A-Za-z0-9-_]+)/gi, (s.join_text == "auto") ? '<a target="_blank" href="http://twitter.com/$1">@$1</a> with ' : '<a target="_blank" href="http://twitter.com/$1">@$1</a>').replace(/[\#]+([A-Za-z0-9-_]+)/gi, '<a href="http://search.twitter.com/search?q=&tag=$1&lang=all&from=' + s.username.join("%2BOR%2B") + '">#$1</a>') +
                                    '</span>&nbsp;' +
                                    '<a href="http://twitter.com/' + item.from_user + '/statuses/' + item.id + '" target="_blank" class="time" title="view tweet on twitter">' + relative_time(item.created_at) + '</a>' +
                                    '</div>');
                });
                list.children('div:odd').addClass('even');
                list.children('div:even').addClass('odd');
                list.children('div:first').addClass('first');
                list.children('div:last').addClass('last');
                if (s.outro_text) list.after(outro);
            });


        });

    };
})(jQuery);


