/*
 * ndSocial - jQuery plugin
 * Facebook and Twitter live feeds updates
 * dbui@nextdigtial 01 2010
 *
 */

(function ($) {

    $.fn.ndSocial = function (options, callback) {
        var url, wrapLink, loading, theObject, html, prevUrl, nextUrl, currentPage, $pagination;

        options = jQuery.extend({
            service: 'facebook', // default service - available options: facebook twitter
            account: 'facebook', // default account
            firstMessageMarkerClass: 'active',
            messagesPerPage: 4,
            totalPages: 3,
            loadingText: null,
            maxCharDisplay: 140
        }, options);

        // wrap urls around <a> if they aren't already
        var wrapLink = function (text) {
            return text.replace(/(href="|<a.*?>)?[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+/g, function ($0, $1) {
                return $1 ? $0 : "<a href='" + $0 + "' target='_blank'>" + $0 + "</a>";
            });
        }

        var addBr = function (text) {
            return text.replace("\n", "<br />");
        }

        // add a "read more" link if the message is longer than limit. message is sliced up to the last space character before the limit (to avoid word breakage)
        var wrapLinkAndAddReadmore = function (text, limit, readmoreUrl) {
            if (text.length <= limit)
                return wrapLink(text);
            else
                return wrapLink(text.slice(0, (text.slice(0, limit)).lastIndexOf(" "))) + "... <span class='readmore'><a href='" + readmoreUrl + "' target='_blank'>read more</a></span>";
        }

        // convert time to "x days ago"
        var relativeTime = function (timeValue, timeFormat) {
            var parsedDate;
            if (timeFormat == "twitter") {
                /* The non-search twitter APIs return inconsistently-formatted dates, which Date.parse
                cannot handle in IE. We therefore perform the following transformation:
                "Wed Apr 29 08:53:31 +0000 2009" => "Wed, Apr 29 2009 08:53:31 +0000" */
                parsedDate = Date.parse(timeValue.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i, '$1,$2$4$3'));
            } else {
                /* Convert Facebook time
                2010-11-29T05:00:00+0000 ==> 2010/11/29 05:00:00 +0000 */
                parsedDate = Date.parse(timeValue.replace(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}:\d{2}:\d{2})(\+\d{4})$/i, '$1/$2/$3 $4 $5'));
            }
            if (isNaN(parsedDate)) return "";
            var relative_to = (arguments.length > 2) ? arguments[2] : new Date();
            var delta = parseInt((relative_to.getTime() - parsedDate) / 1000);
            var r = '';
            if (delta < 60) {
                r = delta + ' seconds ago';
            } else if (delta < 120) {
                r = 'a minute ago';
            } else if (delta < (45 * 60)) {
                r = (parseInt(delta / 60, 10)).toString() + ' minutes ago';
            } else if (delta < (2 * 60 * 60)) {
                r = 'an hour ago';
            } else if (delta < (24 * 60 * 60)) {
                r = '' + (parseInt(delta / 3600, 10)).toString() + ' hours ago';
            } else if (delta < (48 * 60 * 60)) {
                r = 'a day ago';
            } else {
                r = (parseInt(delta / 86400, 10)).toString() + ' days ago';
            }
            return 'about ' + r;
        }

        var showPage = function ($messageItems, $paginationItems, pageIndex) {
            $messageItems.removeClass(options.firstMessageMarkerClass).hide();
            for (var i = 1; i <= options.messagesPerPage; i++) {
                var $thisItem = $messageItems.filter(":nth-child(" + (((pageIndex - 1) * options.messagesPerPage) + i) + ")");
                if (i == 1) $thisItem.addClass(options.firstMessageMarkerClass);
                $thisItem.show();
            }
            $paginationItems.removeClass("active").filter(":nth-child(" + (pageIndex * 1 + 1) + ")").addClass("active");
        }

        var loadWidget = function (theObject, inputUrl) {

            loading = $("<div class='loading'>" + options.loadingText + "</div>");
            if (options.loadingText) theObject.prepend(loading).find("ul.items").remove();

            inputUrl += "&callback=?"; // force callback=? - to be fixed

            // use jQuery getJSON method to fetch the data from the url and then create our unordered list with the relevant data.
            $.ajax({ url: inputUrl, dataType: 'json', success: function (json) {
                html = "<ul class='items'>";

                // loop through and within data array's retrieve the message variable
                if (options.service == "twitter") {
                    options.totalPages = Math.ceil(json.results.length / options.messagesPerPage);
                    $.each(json.results, function (i, tweet) {
                        if (tweet.text !== undefined) {
                            html += "<li>" +
												"<div class='content'>" + addBr(wrapLink(tweet.text)) + "</div>" +
												"<div class='time'><a href='http://twitter.com/" + options.account + "/statuses/" + tweet.id_str + "' target='_blank'>" + relativeTime(tweet.created_at, "twitter") + "</a></div>" +
											"</li>";
                        }
                    });

                } else { // Facebook

                    $.each(json.data, function (i, fb) {
                        if (fb.message) {
                            var readmoreLink = "https://facebook.com/" + options.account + "/posts/" + (fb.id).split("_")[1];
                            html += "<li>" +
												"<div class='content'>" + addBr(wrapLinkAndAddReadmore(fb.message, options.maxCharDisplay, readmoreLink)) + "</div>" +
												"<div class='time'><a href='" + readmoreLink + "' target='_blank'>" + relativeTime(fb.created_time, "facebook") + "</a></div>" +
											"</li>";
                        }
                    });
                }

                html += "</ul>";
                html += "<ul class='pagination'>" +
									"<li>" +
										"<a href='#prev' class='prev'>Previous Page</a>" +
									"</li>";
                for (var i = 1; i <= options.totalPages; i++) {
                    html += "<li>" +
										"<a href='#page" + i + "' class='page'>Page " + i + "</a>" +
									"</li>";
                }
                html += "<li>" +
										"<a href='#next' class='next'>Next Page</a>" +
									"</li>" +
								"</ul>";

                // a little animation once fetched
                theObject.find(".loading").animate({ opacity: 0 }, 500, function () {

                    theObject.html(html);
                    $pagination = theObject.find(".pagination");
                    showPage(theObject.find("ul.items li"), $pagination.find("li"), currentPage);

                    // pagination
                    $pagination.find("a:not(.disabled)").click(function (e) {
                        if ($(this).hasClass('prev'))
                            currentPage--;
                        else if ($(this).hasClass('next'))
                            currentPage++;
                        else {
                            var thisHref = $(this).attr("href");
                            currentPage = thisHref.substring(thisHref.search(/#page/i) + 5); // because in IE7 href is set to full page url
                        }
                        if (currentPage < 1) currentPage = options.totalPages;
                        else if (currentPage > options.totalPages) currentPage = 1;
                        showPage(theObject.find("ul.items li"), $pagination.find("li"), currentPage);
                        e.preventDefault();
                    });

                    // success - run call back function
                    if (typeof callback == 'function') {
                        callback.call(theObject); // brings the scope to the callback
                    }
                });
                theObject.find("ul.items").animate({ opacity: 1 }, 500);

            }
            }); // end ajax
        }

        return this.each(function () {

            currentPage = 1;
            // url for the first load
            if (options.service == "twitter") {
                url = document.location.protocol + "//search.twitter.com/search.json?rpp=" + options.messagesPerPage * options.totalPages + "&q=from:" + options.account + "&page=1";
            } else { // Facebook 
                url = "https://graph.facebook.com/" + options.account + "/posts?limit=" + options.messagesPerPage * options.totalPages + "&access_token=218608034829150|64df6fe13c1bf536019662f0.1-100002525393464|N7TUgYkTQq8ywBLvVpjVz4DDkpY";
            }

            loadWidget($(this), url);
        });
    };

})(jQuery);
