var favesWidget;
var favesSettings;  // last widget's settings
    
if (!favesWidget) { 
    favesWidget = new FavesWidget(); 
}

function FavesWidget() {

    var self;

    self = this;
    self.scopeUser = 0;
    self.scopeFriends = 1;
    self.scopeEveryone = 2;
    self.scopeRecommendations = 4;
    self.defaultCount = 3;
    self.defaultWordLimit = 40;
    self.menuTimeout = 0;
    self.settingsRegistry = {};
    self.stylesheetId = "faves.stylesheet";

    self.init = function(settings) {

        if (document.links.length == 0) {
            return;
        }

        settings.widgetId = "faves." + Math.random();

        self.normalizeSettings(settings);
        self.settingsRegistry[settings.widgetId] = settings;

        var firstFavesLink = document.links[document.links.length - 1];

        for (var i = document.links.length - 1; i >= 0; i--) {

            firstFavesLink = document.links[i];

            if (i == 0 || document.links[i - 1].className != "favesLink") {
                break;
            }

            firstFavesLink.parentNode.removeChild(firstFavesLink);
        }

        var widget = document.createElement("div");

        widget.id = settings.widgetId;
        firstFavesLink.parentNode.replaceChild(widget, firstFavesLink);

        var fn = function() { 
            self.load(settings); 
        } 

        self.attachToOnLoad(fn);
    }

    self.load = function(settings) {

        self.attachStylesheet(settings);

        if (settings.isRecommendations) {
            self.getFaves(self.scopeRecommendations, settings, 1);
        } else if (!settings.hideUserFaves) {
            self.getFaves(self.scopeUser, settings, 1);
        } else if (!settings.hideFriendsFaves) {
            self.getFaves(self.scopeFriends, settings, 1);
        } else {
            self.getFaves(self.scopeEveryone, settings, 1);
        }
    }

    self.attachStylesheet = function(settings) {

        if (document.getElementById(self.stylesheetId) != null) {
            return;
        }

        var link = document.createElement("link");

        link.id = self.stylesheetId;
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = "http://" + settings.hostName + "/css/ScriptWidget.css";

        var heads = document.getElementsByTagName("head");

        if (heads && (heads.length > 0)) {
            heads[0].appendChild(link);
        } else {
            document.body.appendChild(link);
        }
    }

    self.attachToOnLoad = function(fn) {

        if (typeof(window.addEventListener) != "undefined") {

            window.addEventListener("load", fn, false);
            
        } else if (typeof(window.attachEvent) != "undefined") {

            window.attachEvent("onload", fn);
            
        } else {

            if (window.onload != null) {

                var oldOnload = window.onload;

                window.onload = function(e) {
                    oldOnload(e);
                    fn();
                };
            } else {
                window.onload = fn;
            }
        }
    }

    self.render = function(data) {

        var widget = document.getElementById(data.widgetId);
        var settings = self.getSettings(data.widgetId);

        self.normalizeSettings(settings);
        settings.page = data.page;        
        self.outerHtml(widget, self.getWidgetHtml(data, settings));
    }

    self.getSettings = function(widgetId) {

        return self.settingsRegistry[widgetId];    
    }

    self.normalizeSettings = function(settings) {

        // settings.userName; // required
        // settings.userDisplayName // required
        if (self.isUndefined(settings.bodyBackColor)) settings.bodyBackColor = null;
        if (self.isUndefined(settings.count)) settings.count = self.defaultCount;
        if (self.isUndefined(settings.delayTimer)) settings.delayTimer = 0;
        if (self.isUndefined(settings.font)) settings.font = null;
        if (self.isUndefined(settings.footerBackColor)) settings.footerBackColor = null;
        if (self.isUndefined(settings.footerColor)) settings.footerColor = null;
        if (self.isUndefined(settings.footerFontSize)) settings.footerFontSize = null;
        if (self.isUndefined(settings.headerBackColor)) settings.headerBackColor = null;
        if (self.isUndefined(settings.headerColor)) settings.headerColor = null;
        if (self.isUndefined(settings.headerFontSize)) settings.headerFontSize = null;
        if (self.isUndefined(settings.hideEveryonesFaves)) settings.hideEveryonesFaves = false;
        if (self.isUndefined(settings.hideFriendsFaves)) settings.hideFriendsFaves = false;
        if (self.isUndefined(settings.hideNote)) settings.hideNote = false;
        if (self.isUndefined(settings.hidePager)) settings.hidePager = true;
        if (self.isUndefined(settings.hideSubject)) settings.hideSubject = false;
        if (self.isUndefined(settings.hideThumbnail)) settings.hideThumbnail = false;
        if (self.isUndefined(settings.hideUser)) settings.hideUser = false;
        if (self.isUndefined(settings.hideUserFaves)) settings.hideUserFaves = false;
        if (self.isUndefined(settings.hostName)) settings.hostName = "faves.com";
        if (self.isUndefined(settings.isPreview)) settings.isPreview = false;
        if (self.isUndefined(settings.isRecommendations)) settings.isRecommendations = false;
        if (self.isUndefined(settings.noteColor)) settings.noteColor = null;
        if (self.isUndefined(settings.noteFontSize)) settings.noteFontSize = null;
        if (self.isUndefined(settings.noteWordLimit)) settings.noteWordLimit = self.defaultWordLimit;
        if (self.isUndefined(settings.page)) settings.page = 1;
        if (self.isUndefined(settings.subjectColor)) settings.subjectColor = null;
        if (self.isUndefined(settings.subjectFontSize)) settings.subjectFontSize = null;
        if (self.isUndefined(settings.tags)) settings.tags = new Array();
        if (self.isUndefined(settings.theme)) settings.theme = null;
        if (self.isUndefined(settings.title)) settings.title = null;
        if (self.isUndefined(settings.useDotUrl)) settings.useDotUrl = false;
        if (self.isUndefined(settings.useLargeThumbs)) settings.useLargeThumbs = false;
        if (self.isUndefined(settings.useDefaultTopics)) settings.useDefaultTopics = false;
        if (self.isUndefined(settings.userColor)) settings.userColor = null;
        if (self.isUndefined(settings.userFontSize)) settings.userFontSize = null;
        if (self.isUndefined(settings.widgetId)) settings.widgetId = null;
    }

    self.normalizeFave = function(fave) {

        // fave.s is always defined
        // fave.u is always defined
        if (self.isUndefined(fave.n)) fave.n = null;
        if (self.isUndefined(fave.tIU)) fave.tIU = null;
        if (self.isUndefined(fave.uN)) fave.uN = null;
        if (self.isUndefined(fave.uIU)) fave.uIU = null;
    }

    self.getWidgetHtml = function(data, settings) {

        var html = "<div id=\"" + settings.widgetId + "\" class=\"favesWidget";
        var faves = data.faves;
        var showDropdown = self.isDropdownShown(settings);

        if (!self.isNullOrEmpty(settings.theme)) {
            html += " favesTheme " + settings.theme;
        }

        if (!self.isNullOrEmpty(settings.font)) {
            html += "\" style=\"font-family:" + settings.font + " !important;";
        }
        
        html += "\"><h2";

        if ((!self.isNullOrEmpty(settings.headerFontSize)) ||
                (!self.isNullOrEmpty(settings.headerColor)) ||
                (!self.isNullOrEmpty(settings.headerBackColor))) {
                
            html += " style=\"";

            if (!self.isNullOrEmpty(settings.headerFontSize)) {
                html += "font-size:" + settings.headerFontSize + " !important;"; 
            }

            if (!self.isNullOrEmpty(settings.headerColor)) {
                html += "color:" + settings.headerColor + " !important;";
            }

            if (!self.isNullOrEmpty(settings.headerBackColor)) {
                html += "background-color:" + settings.headerBackColor + " !important;";
            }

            html += "\"";
        }

        if (showDropdown) {
            html += " onmouseover=\"favesWidget.showMenu(event, this.childNodes[1]);\" onmouseout=\"favesWidget.hideMenu(event, this.childNodes[1]);\""
        }

        html += ">";

        if (showDropdown) {
        
            html += "<a class=\"favesMenuButton\" href=\"javascript:void(0);\"></a>" +
                "<ul class=\"favesMenu\" style=\"display:none;\" " +
                "onmouseout=\"favesWidget.hideMenu(event, this);\" onclick=\"favesWidget.hideMenu(event, this);\">";

            if (!settings.hideUserFaves) {
                html += "<li><a href=\"javascript:favesWidget.getMyFaves('" + settings.widgetId + "');\">" + settings.userDisplayName + "</a></li>";
            }

            if (!settings.hideFriendsFaves) {            
                html += "<li><a href=\"javascript:favesWidget.getMyFriendsFaves('" + settings.widgetId + "');\">" + settings.userDisplayName + "'s Friends</a></li>";
            }

            if (!settings.hideEveryonesFaves) {
                html += "<li><a href=\"javascript:favesWidget.getEveryonesFaves('" + settings.widgetId + "');\">Everyone</a></li>";
            }
            
            html += "</ul>";
        }

        html += self.htmlEncode(self.getTitle(data.scope, settings)) + "</h2><ul";

        if (!self.isNullOrEmpty(settings.bodyBackColor)) {            
            html += " style=\"background-color:" + settings.bodyBackColor + " !important;\"";
        }

        html += ">";

        for (var i = 0; i < faves.length; i++) {

            var fave = faves[i];

            self.normalizeFave(fave);

            html += "<li>" + 
                self.getFaveImageAndSubject(fave, settings) + 
                self.getFaveUserImageAndName(fave, settings) + 
                self.getFaveNote(fave, settings) + "</li>";
        }

        html += "</ul>";

        if (data.scope != self.scopeRecommendations) {

            html += "<div class=\"favesFooter\"";

            if ((!self.isNullOrEmpty(settings.footerBackColor)) ||
                    (!self.isNullOrEmpty(settings.footerFontSize))) {

                html += " style=\"";

                if (!self.isNullOrEmpty(settings.footerBackColor)) {
                    html += "background-color:" + settings.footerBackColor + " !important;";
                }
            
                if (!self.isNullOrEmpty(settings.footerFontSize)) {
                    html += "font-size:" + settings.footerFontSize + " !important;";
                }

                html += ";\"";
            }

            html += "><a target=\"top" + (settings.isPreview ? "" : "\" href=\"" + 
                self.getHtmlUrl(data.scope, settings, true));

            if (!self.isNullOrEmpty(settings.footerColor)) {
                html += "\" style=\"color:" + settings.footerColor + " !important;";
            }

            html += "\">" + data.moreCount + " More</a> &middot; <a target=\"top" + 
                (settings.isPreview ? "" : "\" href=\"http://" + settings.hostName + "/widget");

            if (!self.isNullOrEmpty(settings.footerColor)) {
                html += "\" style=\"color:" + settings.footerColor + " !important;";
            }

            html += "\">Get your own</a></div>";
                
        } else {

            if (!settings.hidePager) {
                html += "<a class=\"favesLeft\" href=\"javascript:favesWidget.getRecommendations('" + 
                    settings.widgetId + "'," + (settings.page - 1) + ")\">&lt;&lt;</a>" +
                    "<a class=\"favesRight\" href=\"javascript:favesWidget.getRecommendations('" + 
                    settings.widgetId + "'," + (settings.page + 1) + ")\">&gt;&gt;</a>";
            }
        }

        html += "</div>";

        return html;
    }

    self.isDropdownShown = function(settings) {

        var i = 0;

        if (settings.isRecommendations) {
            return false;
        }

        if (!settings.hideUserFaves) {
            i++;
        }

        if (!settings.hideFriendsFaves) {
            i++;
        }

        if (!settings.hideEveryonesFaves) {
            i++;
        }

        return (i > 1);
    }

    self.getTitle = function(scope, settings) {

        var title = self.isNullOrEmpty(settings.title) ? "" : settings.title + " ";

        switch (scope) {

            case self.scopeUser:

                if ((settings.hideFriendsFaves) && (settings.hideEveryonesFaves)) {
                    return title;
                } else {
                    return title + "from " + settings.userDisplayName;
                }

            case self.scopeFriends:
                return title + "from " + settings.userDisplayName + "'s Friends";

            case self.scopeEveryone:
                return title + "from Everyone";

            case self.scopeRecommendations:
                return title;
        }
    }

    self.showMenu = function(event, menu) {

        self.cancelBubble(event);
        window.clearTimeout(self.menuTimeout);    
        menu.style.display = "";
    }

    self.hideMenu = function(event, menu) {

        self.cancelBubble(event);
        window.clearTimeout(self.menuTimeout);    
        self.menuTimeout = window.setTimeout(function() { self.reallyHideMenu(menu); }, 150);
    }

    self.cancelBubble = function(event) {

        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    }

    self.reallyHideMenu = function(menu) {

        menu.style.display = "none";
    }

    self.getMyFaves = function(widgetId) {
        
        self.getFaves(self.scopeUser, self.getSettings(widgetId), 1);
    }

    self.getMyFriendsFaves = function(widgetId) {

        self.getFaves(self.scopeFriends, self.getSettings(widgetId), 1);
    }

    self.getEveryonesFaves = function(widgetId) {

        self.getFaves(self.scopeEveryone, self.getSettings(widgetId), 1);
    }

    self.getRecommendations = function(widgetId, page) {

        self.getFaves(self.scopeRecommendations, self.getSettings(widgetId), page);
    }

    self.getFaves = function(scope, settings, page) {

        var script = document.createElement("script");

        script.src = self.getJsonUrl(scope, settings, "favesWidget.render", page);
        document.body.appendChild(script);
    }

    self.refresh = function(settings) {

        self.normalizeSettings(settings);
        self.getFaves(self.scope, settings);
    }

    self.getJsonUrl = function(scope, settings, callback, page) {

        var url;

        if (scope == self.scopeRecommendations) {
            url = "http://" + settings.hostName + "/RecommendationsWidget.ashx";
        } else if (scope == self.scopeEveryone) {
            url = "http://" + settings.hostName + "/json/buzz" + self.getTagsUrlFragment(self.scopeEveryone, settings.tags);
        } else {
            url = self.getHtmlUrl(scope, settings, false) + "/json";
        }

        url += "?callback=" + encodeURIComponent(callback) + "&scope=" + scope + "&page=" + page;

        if (settings.widgetId != null) {
            url += "&widgetId=" + settings.widgetId;
        }

        if (settings.count != self.defaultCount) {
            url += "&count=" + settings.count;
        }

        if (settings.hideThumbnail) {
            url += "&hideThumbnail=1";
        }

        if (settings.hideUser) {
            url += "&hideUser=1";
        }

        if (settings.hideNote) {
            url += "&hideNote=1";
        }

        if (settings.useDotUrl) {
            url += "&useDotUrl=1";
        }

        if (settings.useLargeThumbs) {
            url += "&useLargeThumbs=1";
        }

        if (settings.useDefaultTopics) {
            url += "&useDefaultTopics=1";
        }

        if (settings.tags.length == 0) {
            return url;
        }

        if (scope != self.scopeEveryone) {

            url += "&st=";

            for (var i = 0; i < settings.tags.length; i++) {

                if (i > 0) {
                    url += "+";
                }
                
                url += encodeURIComponent("tag:\"" + self.trim(settings.tags[i]) + "\"");
            }
        }
        
        return url;
    }

    self.getHtmlUrl = function(scope, settings, includeTags) {

        var url = "http://" + settings.hostName;

        switch (scope) {

            case self.scopeUser:
                url += "/users/" + encodeURIComponent(settings.userName);
                break;
                
            case self.scopeFriends:
                url += "/users/" + encodeURIComponent(settings.userName) + "/friends";
                break;

            case self.scopeEveryone:
                url += "/buzz";
                break;

            case self.scopeRecommendations:
                url += "/Recommendations";
                break;
        }

        if (!includeTags) {
            return url;
        }

        return url + self.getTagsUrlFragment(scope, settings.tags);
    }

    self.getTagsUrlFragment = function(scope, tags) {

        if (tags.length == 0) {
            return "";
        }

        var url = ""

        if (scope != self.scopeEveryone) {        
            url += "/tag";
        }

        for (var i = 0; i < tags.length; i++) {
            url += "/" + encodeURIComponent(self.trim(tags[i]));
        }

        return url;
    }

    self.htmlEncode = function(s) {

        return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;");
    }

    self.getFaveImageAndSubject = function(fave, settings) {

        var html = "<h3><a target=\"top" + (settings.isPreview ? "" : "\" href=\"" + fave.u);

        if (!self.isNullOrEmpty(settings.subjectColor) ||
                !self.isNullOrEmpty(settings.subjectFontSize)) {

            html += "\" style=\"";

            if (!self.isNullOrEmpty(settings.subjectColor)) {
                html += "color:" + settings.subjectColor + " !important;";
            }

            if (!self.isNullOrEmpty(settings.subjectFontSize)) {
                html += "font-size:" + settings.subjectFontSize + " !important;";
            }
        }

        if (!self.isNullOrEmpty(fave.s)) {
            html += "\" title=\"" + fave.s;
        }

        html += "\">";

        if (!settings.hideThumbnail) {

            html += "<span";

            if (!self.isNullOrEmpty(fave.tIU)) {
                html += " style=\"background-image:url('" + fave.tIU + "') !important;\""; 
            }

            html += "></span>";
        }

        if (!settings.hideSubject) {
            html += self.htmlEncode(fave.s);
        }

        html += "</a></h3>";
        
        return html;
    }

    self.getFaveUserImageAndName = function(fave, settings) {

        if (self.isNullOrEmpty(fave.uIU) && self.isNullOrEmpty(fave.uN)) {
            return "";
        }

        var html = "<div><a target=\"top" + (settings.isPreview ? "" : "\" href=\"" + fave.u);

        if ((!self.isNullOrEmpty(settings.userFontSize)) ||
                (!self.isNullOrEmpty(settings.userColor))) {

            html += "\" style=\"";

            if (!self.isNullOrEmpty(settings.userFontSize)) {
                html += "font-size:" + settings.userFontSize + " !important;";
            }

            if (!self.isNullOrEmpty(settings.userColor)) {
                html += "color:" + settings.userColor + " !important;";
            }
        }

        html += "\">";
        
        if (!self.isNullOrEmpty(fave.uIU)) {
            html += "<img src=\"" + fave.uIU + "\" alt=\"\" />";
        }

        if (!self.isNullOrEmpty(fave.uN)) {
            html += self.htmlEncode(fave.uN);
        }

        html += "</a></div>";
        
        return html;
    }

    self.getFaveNote = function(fave, settings) {

        if (fave.n == null) {
            return "";
        }

        var html = "<p";
        var words = fave.n.split(" ");
        var content;

        if ((!self.isNullOrEmpty(settings.noteFontSize)) ||
                (!self.isNullOrEmpty(settings.noteColor))) {

            html += " style=\"";

            if (!self.isNullOrEmpty(settings.noteFontSize)) {
                html += "font-size:" + settings.noteFontSize + " !important;";
            }

            if (!self.isNullOrEmpty(settings.noteColor)) {
                html += "color:" + settings.noteColor + " !important;";
            }

            html += "\"";
        }

        if ((settings.noteWordLimit != -1) && (words.length >= settings.noteWordLimit)) {
            words.length = settings.noteWordLimit;
            content = words.join(" ") + "...";        
        } else {
            content = fave.n;
        }

        content = self.trim(content);
        html += ">" + self.htmlEncode(content).replace(/\n/g, "<br/>") + "</p>";

        return html;
    }

    self.isUndefined = function(o) {

        return (typeof(o) == "undefined");
    }

    self.isNullOrEmpty = function(s) {

        return (s == null) || (s.length == 0);
    }

    self.trim = function(s) {
        
        return s.replace(/^\s+|\s+$/g, "");
    }

    self.outerHtml = function(o, html) {

        var div = document.createElement("div");

        div.innerHTML = html;
        o.parentNode.replaceChild(div.childNodes[0], o);
    }
}

function favesRenderWidget() {
    // no-op
}

favesWidget.init(favesSettings);
