//Note to editor: NOT executed from XUL
//Copyright 2009 Yongqian Li.

(function()
{
    var yandex_lang_codes = ['ru', 'rus',
        'uk', 'ukr',
        'be', 'bel',
        'kk', 'kaz',
        'uz', 'uzb',
        'kaa', 'kaa',
        'tk', 'tuk',
        'tut', 'gag',
        'mo', 'mol',
        'ky', 'kir',
        'et', 'est',
        'lt', 'lit',
        'lv', 'lav',
        'hy', 'arm', 'hye', 
        'az', 'aze',
        'ka', 'geo', 'kat',
        'tg', 'tgk'];

    var show_yandex = false;
    for(var x = 0; x < yandex_lang_codes.length; x++)
    {
        if(navigator.language == yandex_lang_codes[x] || navigator.language.indexOf(yandex_lang_codes[x] + "-") == 0)
        {
            show_yandex = true;
        }
    }


    /* //BEGIN FasterFox widget specific code
    var $ = window.finderfox_$
    var config = {
        showPopupBubble: true,
        openNewTab: true,
        forceSingleRow: false,
        animate: true,
        enableGhosting: false,
        source: "finderfox",

        customSearchEngines: [],

        searchWikipedia: true,
        searchOneRiot: true,
        searchYandex: false,        
        searchDelicious: false,
        searchTwitter: false,
        searchSurfCanyon: true,
        tweetThis: true,
        searchBing: false,
        searchBaidu: false,
        searchReddit: false,
        searchYouTube: false,
        searchWiktionary: false,
        searchGoogle: true,        
        showHomepageLink: true
    };    
    if(!$.support.opacity)
    {
        config.animate = false;
    }
    
    if(show_yandex && config.searchGoogle && !config.searchYandex)
    {
        //default config, override
        config.searchGoogle = false;
        config.searchYandex = true;
    }

    var ext_config = window.finderfoxConfig;
    if(ext_config)
    {
        if(ext_config.customSearchEngines && 
           ext_config.customSearchEngines.length > 0)
        {
            config.customSearchEngines = [ext_config.customSearchEngines[0]];
            config.searchTwitter = false;
        }        
    }
    window.finderfox = {
        //config: config,
        disable: function()
        {
            config.showPopupBubble = false;
        }
    };
    */ //END FasterFox widget specific code
    
    //BEGIN SmarterFox specific code
    //var $ = smarterwiki_$;
    var safe_SW_getBoolPref = function(name)
    {
        try
        {
            return SW_getBoolPref(name);
        }
        catch(err)
        {
            return null;
        }
    };
    var getBoolPref = function(pref_name, callback)
    {
        callback(safe_SW_getBoolPref("extensions.smarterwiki." + pref_name));
    };
    
    var config = {
        get showPopupBubble() 
        {
            if(unsafeWindow.finderfox)
            {
                /*
                if(safe_SW_getBoolPref("extensions.smarterwiki.show_popup_bubble")) //I override the embedded
                {
                    unsafeWindow.finderfox.disable(); 
                    return true;
                }
                */
                return false; //the embedded widget overrides me
            }
            return safe_SW_getBoolPref("extensions.smarterwiki.show_popup_bubble");
        },
        get openNewTab() 
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.popup_bubble_open_new_tab");
        },
        get forceSingleRow()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.popup_bubble_force_single_row");
        },
        animate: true,
        enableGhosting: true,
        source: "smarterfox",
        get customSearchEngines()
        {
            return [
            /*
                [
                    "Diig search", 
                    "http://www.digg.com/favicon.ico", 
                    "http://diig.com{searchTerms}"
                ],
                [
                    "Diig search", 
                    "http://www.digg.com/favicon.ico", 
                    "http://diig.com{searchTerms}"
                ],
            */
            ];
            //return [];
        },

        get searchWikipedia()
        {
            return true;
        },
        get searchOneRiot()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_oneriot");
        },
        get searchDuckDuckGo()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_duckduckgo");
        },
        get searchYandex()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_yandex");
            /*
            var pref_searchYandex = safe_SW_getBoolPref("extensions.smarterwiki.search_yandex");
            var pref_searchGoogle = safe_SW_getBoolPref("extensions.smarterwiki.search_google");
            if(show_yandex && pref_searchGoogle && !pref_searchYandex)
            {
                //default config, override
                return true;
            }
            return pref_searchYandex;
            */
        },
        get searchDelicious()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_delicious");
        },
        get searchTwitter()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_twitter");
        },
        get searchSurfCanyon()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_surfcanyon");
        },
        get tweetThis()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.tweet_this");
        },
        get searchBing()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_bing");
        },
        get searchBaidu()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_baidu");
        },
        get searchReddit()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_reddit");
        },
        get searchYouTube()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_youtube");
        },
        get searchWiktionary()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_wiktionary");
        },
        get searchGoogle()
        {
            return safe_SW_getBoolPref("extensions.smarterwiki.search_google");
            /*
            var pref_searchYandex = safe_SW_getBoolPref("extensions.smarterwiki.search_yandex");
            var pref_searchGoogle = safe_SW_getBoolPref("extensions.smarterwiki.search_google");
            if(show_yandex && pref_searchGoogle && !pref_searchYandex)
            {
                //default config, override
                return false;
            }
            return pref_searchGoogle;
            */
        },
        showHomepageLink: false,
    };    
    //END SmarterFox specific code


    var get_config = function(callback)
    {
        callback(config);
    };
    if(window.chrome && window.chrome.extension) // detect chrome
    {
        $.prototype.ready = function(callback) {
            callback();
        };//doesn't work on Chrome, cheap hack
        
        get_config = function(callback)
        {
            var config = {
                animate: true,
                enableGhosting: true,
                source: "smarterfox",
                customSearchEngines: [],
                searchWikipedia: true,
                showHomepageLink: false
            };
            var config_map = {
                showPopupBubble: "show_popup_bubble",
                openNewTab: "popup_bubble_open_new_tab",
                forceSingleRow: "popup_bubble_force_single_row",
                searchOneRiot: "search_oneriot",
                searchDuckDuckGo: "search_duckduckgo",
                searchYandex: "search_yandex",
                searchDelicious: "search_delicious",
                searchTwitter: "search_twitter",
                searchSurfCanyon: "search_surfcanyon",
                tweetThis: "tweet_this",
                searchBing: "search_bing",
                searchBaidu: "search_baidu",
                searchReddit: "search_reddit",
                searchYouTube: "search_youtube",
                searchWiktionary: "search_wiktionary",
                searchGoogle: "search_google"
            };
            
            var get_localStorage = function(key, callback) //only used for Chrome
            {    
                chrome.extension.sendRequest({"msg_type": "get_localStorage", "key": key}, function(response)
                {
                    if(callback)
                    {
                        callback(response.value);
                    }
                });
            };
            getBoolPref = function(pref_name, callback)
            {
                get_localStorage("pref." + pref_name, function(str)
                {
                    callback(str == "true");
                });
            };

            for(var key in config_map)
            {
                (function(prop_name)
                {
                    getBoolPref(config_map[prop_name], function(pref_value)
                    {
                        config[prop_name] = pref_value;
                        config_map[prop_name] = null;
                        for(var prop_name2 in config_map) {
                            if(config_map[prop_name2]) {
                                return;
                            }
                        }
                        /*
                        if(window.finderfox) {
                            config["showPopupBubble"] = false;
                        }*///doesn't work :(
                        callback(config);
                    });
                })(key);
            }
        };
    }
    



    var get_log_msg_url = function(msg)
    {
        msg["rand"] = parseInt(Math.random() * 1000000000);
        var params = [];
        for(var k in msg)
        {
            params.push(encodeURIComponent(k) + "=" + encodeURIComponent(msg[k]));
        }
        /*
        if("https:" == document.location.protocol)
        {
            return "https://ssl.msgs.smarterfox.com/log_msg?" + params.join("&");
        }
        */
        return "http://msgs.smarterfox.com/log_msg?" + params.join("&");
    };
    

    var log_msg_async = function(msg, callback)
    {
        var $ting = $('<img style="display: none;" />');
        if(callback)
        {
            $ting.load(callback);
        }
        $ting.attr("src", get_log_msg_url(msg));
        return $ting;
    };

    
    /*//doesn't work for some reason :(
    var log_msg_async = function(msg, callback)
    {
        var ting = new Image(1, 1);
        if(callback)
        {
            ting.onload = callback;
        }
        ting.src = get_log_msg_url(msg);
        return ting;
    };
    */
    
    var track_click = function($a, msg)
    {
        $a.mouseup(function(event)
        {
            var original_href = $a.attr("href");
            msg["redirect_to"] = original_href;
            $a.attr("href", get_log_msg_url(msg));

            setTimeout(function()
            {
                $a.attr("href", original_href);
            }, 10);
        });
    };        
    
    
    /*
    var log_msg_blocking = function(msg)
    {
        try
        {
            var req = new XMLHttpRequest();
            req.open("GET", get_log_msg_url(msg), false);   
            req.send(null);  
            return req;
        }
        catch(ex)
        {
        }
    };
    */

    var arrayDeepEq = function(a1, a2)
    {
        if(a1.length != a2.length)
        {
            return false;
        }
        for(var i = 0; i < a1.length; i++)
        {
            if(a1[i] != a2[i])
            {
                return false
            }
        }
        return true;
    };

    var isDesignMode = function(doc)
    {
        return !(document.designMode == "off"
                || doc.designMode == "Off" || doc.designMode == "Inherit") // hack for IE
    };
    
    var isLeftClick = function(event)
    {
        return (!$.browser.msie && event.button == 0) 
            || ($.browser.msie && event.button == 1); // hack for IE
    };

    var getSelection = function(doc)
    {
        try
        {
            return doc.defaultView.getSelection(); // correct way for Firefox
        }
        catch(err){}
        try
        {
            return window.getSelection(); // hack for IE
        }            
        catch(err){}
        try
        {
            return document.getSelection(); // hack for IE
        }            
        catch(err){}
        try // hack for IE
        {
            var selection = document.selection && document.selection.createRange();
            selection.toString = function() { return this.text };
            return selection;
        }            
        catch(err){}
        return null;
    };

    var getLastRange = function(selection)
    {
        var lastRange = selection.getRangeAt(selection.rangeCount - 1);
        for(var r = selection.rangeCount - 1; r >= 0; r--)
        {
            if(!selection.getRangeAt(r).collapsed) {
                lastRange = selection.getRangeAt(r);
                break;
            }
            else {
                //alert("invalid range found");
            }
        } //fix Firefox bug? with selecting backwards: it creates an range at the end that is collapsed
        return lastRange;
    };        
    
    var isValidSelection = function(selection)
    {
        try
        {
            /*
            //alert(selection.toString() + ":" + 
                selection.anchorNode.nodeName + 
                ":" + selection.anchorOffset + ":" + 
                selection.focusNode.nodeName + ":" + selection.focusOffset + ":" + selection.isCollapsed);
            //alert(selection.anchorNode == selection.focusNode);
            */
            if(selection.toString())
            {
                if(selection.anchorNode.nodeName.toLowerCase() == "object")
                {//fix problems with flash players on myspace such as http://www.myspace.com/entershikari
                    return false;
                }
                if(selection.anchorNode == selection.focusNode && 
                    selection.toString().replace(/^\s+|\s+$/g,"").length > Math.abs(selection.focusOffset - selection.anchorOffset))
                {//fix <a> with title button on http://news.bbc.co.uk/2/hi/middle_east/8098776.stm
                    return false;
                }
                /*
                if(!(selection.anchorNode.nodeName.toLowerCase() == "#text" && 
                     selection.focusNode.nodeName.toLowerCase() == "#text"))
                {//too restrictive
                    return false;
                }
                */
                var containsInput = false;
                $("textarea, input[type=text]", doc).each(function(i)
                {
                    if(selection.containsNode(this, true))
                    {
                        containsInput = true; //contains input/textarea
                        return false;//break
                    }
                });
                return !containsInput;
            }
            else
            {
                return false;
            }
        }
        catch(err) //dirty hack for IE
        {
            return selection.toString();
        }
    };
    
    var show_popup_bubble = function(doc)
    {
        //"popup_bubble_loaded"
        var getSelectionKey = function(selection)
        {
            try
            {
                var lastRange = getLastRange(selection);//selection.getRangeAt(selection.rangeCount - 1);
                return [selection.toString(), lastRange.endContainer, lastRange.endOffset];
            }
            catch(err)
            {   //alert("using hack"); //dirty IE hack
                return [selection.toString()];
            }
        };

        //BEGIN preview code
        var homepageURL = "http://smarterfox.com/widget/";

        var getSearchResultsURL = function(url, terms)
        {
            var language = navigator.language ? navigator.language : navigator.userLanguage;
            var url = url.replace(/{searchTerms}/g, encodeURIComponent(terms));
            url = url.replace(/{language}/g, language);
            return url;
        };
        var searchWikipediaURL = "http://api3.smarterfox.com/wikisearch/search?q={searchTerms}&locale={language}";
        var searchWikipediaURL2 = "http://api4.smarterfox.com/wikisearch/search?q={searchTerms}&locale={language}";
        var searchOneRiotURL = "http://www.oneriot.com/search?p=smarterfox&ssrc=" + config.source + "_popup_bubble&spid=8493c8f1-0b5b-4116-99fd-f0bcb0a3b602&q={searchTerms}";
        var searchYandexURL = "http://yandex.ru/yandsearch?text={searchTerms}&clid=127504";
        var searchDeliciousURL = "http://delicious.com/search?p={searchTerms}";
        var searchTwitterURL = "http://search.twitter.com/search?q={searchTerms}";
        var searchSurfCanyonURL = "http://search.surfcanyon.com/search?f=nrl1&q={searchTerms}&partner=fastestfox";
        var tweetThisURL = "http://twitter.com/home?status={searchTerms}";
        var searchBingURL = "http://www.bing.com/search?q={searchTerms}";
        var searchBaiduURL = "http://www.baidu.com/s?wd={searchTerms}";
        var searchRedditURL = "http://www.reddit.com/search?q={searchTerms}";
        var searchYouTubeURL = "http://www.youtube.com/results?search_query={searchTerms}";
        var searchWiktionaryURL = "http://en.wiktionary.org/wiki/Special:Search?search={searchTerms}&go=Define";
        var searchGoogleURL = "http://www.google.com/search?q={searchTerms}";
        
        var searchDuckDuckGoURL = "http://duckduckgo.com/?q={searchTerms}";
        var searchDuckDuckGoAPIURL = "http://ff.duckduckgo.com/?q={searchTerms}&o=json&d=1";


        var get_definition = function(searchQuery, onsuccess)
        {
            SW_$.get(getSearchResultsURL(searchDuckDuckGoAPIURL, searchQuery), {}, function(data)
            {
                var res = data["Abstract"]
                if(res == "")
                {
                    res = data["RelatedTopics"][0]["Result"];
                }
                var ddg_cite = '<a href="' + getSearchResultsURL(searchDuckDuckGoURL, searchQuery) + '" title="Search DuckDuckGo"><img src="http://ff.duckduckgo.com/favicon.ico" alt="DuckDuckGo" /></a>';
                onsuccess('<b>' + data["AbstractSource"] + ':</b> ' + res + ' <a href="' + getSearchResultsURL(searchDuckDuckGoURL, searchQuery) + '"><b>&#xbb;</b></a>');
            }, "json");
        };        
        
        var buildPopupSearchBubbleLite = function(config, searchQuery)//, insertCallback) //dirty hack for IE
        {
            var $popupBubble = $('<a class="smarterwiki-popup-bubble smarterwiki-popup-bubble-lite smarterwiki-popup-bubble-active" href="' 
                + getSearchResultsURL(searchWikipediaURL, searchQuery) + '"></a>', doc);
            if(config.openNewTab)
            {
                $popupBubble.attr("target", "_blank");
            }
            //insertCallback($popupBubble);
            return $popupBubble;     
        };
        
        var buildPopupSearchBubbleLinks = function(config, searchQuery, forceSingleRow)
        {
            var $popupBubbleLinks = $(
                '<span class="smarterwiki-popup-bubble-links smarterwiki-clearfix"></span>',
                doc);
                
            var homepageLink = function(classes)
            {
                var $a = $('<a href="' + homepageURL + '" class="' + classes + '"></a>', doc);
                if(config.openNewTab)
                {
                    $a.attr("target", "_blank");
                }
                track_click($a, {name: "homepage_visited", source: config.source});
                return $a;
            };

            var bubbleLinkAs = [];

            var addBubbleLink = function(title, icon_src, href, track)
            {
                var $a = $('<a class="smarterwiki-popup-bubble-link"></a>', doc)
                        .attr("href", href)
                        //.attr("href", "#")
                        .attr("title", title)
                        .append(
                            $('<img alt="" class="smarterwiki-popup-bubble-link-favicon" />', doc)
                            .attr("src", icon_src)
                        );

                if(config.openNewTab)
                {
                    $a.attr("target", "_blank");
                }
                
                if(track)
                {
                    track_click($a, {name: "popup_bubble_searched", search_engine_title: title, source: config.source});
                }

                bubbleLinkAs.push($a);
                return $a;
            };

            //addBubbleLink("http://static.smarterfox.com/media/wiki-favicon.png", searchWikipediaURL(searchQuery), "Search Wikipedia");
            if(config.searchWikipedia)
            {
                addBubbleLink(
                    "Search Wikipedia",
                    //"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAIpwAACKcBMsYCAwAAAAd0SU1FB9kFEwgQLXKnj9oAAAPsSURBVDiNdVRZSGRXEH1Joz8icSIMJsEQEvKvov4ICoOYIAp+KKISkLiAgij5UGOMjgoug6CiKC64i/sSpVHcl7jv7W6722pcWmyNoqBW6hRpyYSZC8W7975bdU+dOrcUIlL+axYWFq+SkpLybWxsYo17VlZWX/H6DebOzs4/ent7/+Lu7v7z/31h7y8U5fvV1VWNra3tIObGvZqamtaHh4fHxMTExb29vcejoyMKCwt7jIqKWuD/bz4Y0MXF5e319bU2JyfngA99x/YJ22empqZuERERKwcHB9Td3U37+/u0srJCc3NzNDIyQk1NTVcqleonPvv6JSCPL87OznQ8p+TkZC2vv2GzcnNz+83a2joqLy9vCQFnZ2dpfX2dlpaWqLe3lzo7O+WStLS0ORMTE7+XgCkpKTX07/Dz86PIyEhDVlaWISMjgxISEmRfp9PRzs4O7e7uEtMi6EZHRyVweHg4gp6bm5tbKK958PlbODES+ZmZmQmkxjsE2d3dHWm1WsrOzqa6ujoaGhqigYEBGh4epvT0dCovLyd7e3sfhR3fGR0vLy9fULa0tMj8/PycNBoNcVGIi0NxcXHU09NDY2Nj1N/fL2mXlZXJJV5eXkXK9va2DojggIDPz8/iuLGxQcvLy8IXEN7c3JBer5f14uKiIOzr66P29naqqqqiiooK8vf3n1aYbP3ExIQcZkkIKgcHBwJ/BoNB1ltbW8IbF466urrk3OTkpFhDQ4MEZA7Jx8fnSGEJ6I2pHh4eyvf2ViglVBbBwBMQb25u0sLCgnAXExMjVLS1tVFJSYmkHRoa+pfCmydwPjk5EYf7+3txwBoVRTFmZmZetFdcXEyBgYGUm5srVa6traWioiIqKCig4ODgVYVJnUE6LGpBhLQQDMjAHeaQzPT0tASG7iorK0U2kAwC4hIE9PT0HFZYvB7j4+NPQHlxcSGFOD4+Fvnw8xKOUGnwxAWkqakpqSz7CJ/V1dXEmiV+/+To6Pi7CJvFq356ehIHaA2ogPjq6krSRlVbW1ulqoODgyIbyMfX15dKS0spNjYWAf+2tLT8UgLyJAIPHinPz89LFcEXJIJUcdHa2ppIBAjVajWlpqYSNwcqLCwUdEFBQX9+ysP4llXcSf7gFO6A8PT0lJqbm4UXvB6kBc6QKgz/sAfu8Ers7OzecYxv3+s2PD53dXX9FVUFCiCqr6+njo4OSRMBwSN3FylKfn4+MQgKCAhAC1N9rB+aODk5vWUU5+ARUoHu8CpQ0cbGRjFcxA3kkjtRAft8/dEGazRuRabcZH8ICQkpjo6OVjNHmvj4+GXuiyMeHh453ATCzMzMXn3I9x8oCiuuorpqawAAAABJRU5ErkJggg==",
                    "http://static.smarterfox.com/media/wiki-favicon-sharpened.png", 
                    getSearchResultsURL(searchWikipediaURL, searchQuery),
                    true
                );
            }
            
            for(var s = 0; s < config.customSearchEngines.length; s++)
            {
                addBubbleLink(
                        config.customSearchEngines[s][0], 
                        config.customSearchEngines[s][1],
                        getSearchResultsURL(config.customSearchEngines[s][2], searchQuery),
                        true                        
                );
            }

            if(config.searchOneRiot)
            {
                addBubbleLink(
                    "Search OneRiot",
                    //"data:;base64, ",
                    //"http://www.oneriot.com/images/favicon.ico", 
                    "http://static.smarterfox.com/media/popup_bubble/oneriot-favicon.ico",
                    getSearchResultsURL(searchOneRiotURL, searchQuery),
                    true                    
                );
            }

            if(config.searchDuckDuckGo)
            {
                addBubbleLink(
                    "Search DuckDuckGo",
                    //"data:;base64, ",
                    //"http://www.oneriot.com/images/favicon.ico", 
                    "http://ff.duckduckgo.com/favicon.ico",
                    getSearchResultsURL(searchDuckDuckGoURL, searchQuery),
                    true                    
                );
            }

            if(config.searchDelicious)
            {
                addBubbleLink(
                    "Search Delicious",
                    "http://delicious.com/favicon.ico", 
                    getSearchResultsURL(searchDeliciousURL, searchQuery),
                    true
                );
            }
            if(config.searchSurfCanyon)
            {
                addBubbleLink(
                    "Search Surf Canyon",
                    "http://surfcanyon.com/favicon.ico", 
                    getSearchResultsURL(searchSurfCanyonURL, searchQuery),
                    true
                );
            }            
            if(config.searchTwitter)
            {
                addBubbleLink(
                    "Search Twitter",
                    //"data:;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAADw4ikA7d0HAO3cAAD16nwA8+doAP7+/QDz52cA/PrpAPTpdgD9/f0A///+AP39/gD8/PkA7d0IAPv42QD9/fwA/P3/APv2yADs2gAA+/v4APv2xwD264QA8OI5APPnZgDu3QAA+PGgAPXqgADx5E4A9+6aAO/gGAD164UA9ep+APDiOAD+/foA+fr6APfulADx5VAA7dsAAPz89QD37pMA9up8APz8/AD8+dcA/PjUAPz3zQD79MIA+/r4AP7++AD8/PsA/frnAPr1vgD7+eEA9uyLAP7+/AD9+/AA9eyFAPz54QD7+/YA7+EjAPr31QD48KUA9ep3APz53gD16n8A/Pv5APjxpgD48akA+/vxAPr7+gDz6GgA798AAP388gDx5EYA9Ol1APXqdQDu3hkA8uZYAPPnXgD+/v8A/PvzAP7//gDv4AAA/v//APz79AD48bEA+fO0APbsjAD7+NwA/fvtAPbtkADv4BQA+/jfAPv42gD79soA8+dgAPPmYwD9/PoA/f37APz8+AD9/PkA+fS8APDjOgD8/PcA+/fYAPbuigD69sYA+PGiAPv65gD37pYA/PrxAOzbAAD69s8A/PrqAPbthgD16XYA9elxAPv69QD8+uIA+/jYAPv54wD69tQA7NwAAPjxpAD48Z4A7t4AAP7+/gD///8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAgAUibVx2Dg52TwyAgICAgA8JIzoBAQ0NAiBHgICAgAVjTRIYfHx8fHwSMoCAgIAQcW58fAICAnklSzGAgIB9QwBGUVpoQWoZej6AgICAfXg6AB17EAkLCylQgICAgFJvZUgWaTAKfX01gICAgIBOOyRMG2Q2B3AHayGAgICAfWdeBEUEBgQGBl83L4CAgIBXcz0ICElKcgg9FyqAgICAWz8VHh8DAygDAxpYgICAfTM0WVZVXREUFBF1YICAgH13bBwnPkQTEy5AD4CAgIB9B0JUPDgMgICAgICAgICACmYrLSwmBYCAgICAgICAgIBhdFM5YoCAgICAgICAgPADAADgAwAAwAMAAMADAACABwAAgAcAAIAPAACABwAAgAMAAMADAADAAwAAgAMAAIAHAACA/wAAgP8AAMH/AAA=",
                    "http://twitter.com/favicon.ico", 
                    getSearchResultsURL(searchTwitterURL, searchQuery),
                    true
                );
            }
            if(config.tweetThis)
            {
                addBubbleLink(
                    "Tweet This!",
                    "http://static.smarterfox.com/media/finderfox/tweet_this.png", 
                    getSearchResultsURL(tweetThisURL, '"' + searchQuery + '" - ' + doc.location.href),
                    true                    
                );
            }
            if(config.searchBing)
            {
                addBubbleLink(
                    "Search Bing",
                    "http://www.bing.com/favicon.ico", 
                    getSearchResultsURL(searchBingURL, searchQuery),
                    true                    
                );
            }
            if(config.searchBaidu)
            {
                addBubbleLink(
                    "Search Baidu",
                    "http://www.baidu.com/favicon.ico", 
                    getSearchResultsURL(searchBaiduURL, searchQuery),
                    true                    
                );
            }
            if(config.searchReddit)
            {
                addBubbleLink(
                    "Search Reddit",
                    "http://www.reddit.com/favicon.ico", 
                    getSearchResultsURL(searchRedditURL, searchQuery),
                    true                    
                );
            }
            if(config.searchYouTube)
            {
                addBubbleLink(
                    "Search YouTube",
                    "http://www.youtube.com/favicon.ico", 
                    getSearchResultsURL(searchYouTubeURL, searchQuery),
                    true                    
                );
            }            
            if(config.searchWiktionary)
            {
                addBubbleLink(
                    "Search Wiktionary",
                    "http://en.wiktionary.org/favicon.ico", 
                    getSearchResultsURL(searchWiktionaryURL, searchQuery),
                    true                    
                );
            }
            if(config.searchGoogle)
            {
                addBubbleLink(
                    "Search Google",
                    //"data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7PT7/3zF6/9Ptu//RbHx/0227/+Tzvb/9vv5/97h0f9JeBz/NHoA/z98Av9AfAD/PHsA/0F6AP8AAAAA/vz7/1+33/8Mp+z/FrHw/xWy8f8bs/T/Hqrx/3zE7v////7/t8qp/zF2A/87gwH/P4ID/z59AP8+egD/Q3kA/97s8v8botj/ELn3/wy58f8PtfL/D7Lw/xuz9P8vq+f/8/n///779v9KhR3/OYYA/0GFAv88hgD/QIAC/z17AP/0+/j/N6bM/wC07/8Cxf7/CsP7/wm+9v8Aqur/SrDb//7+/v///P7/VZEl/zSJAP87jQD/PYYA/0OBBf8+fQH///3//9Dp8/84sM7/CrDf/wC14/8CruL/KqnW/9ns8f/8/v//4OjX/z+GDf85kAD/PIwD/z2JAv8+hQD/PoEA/9C7pv/97uv////+/9Xw+v+w3ej/ls/e/+rz9///////+/z6/22mSf8qjQH/OJMA/zuQAP85iwL/PIgA/zyFAP+OSSL/nV44/7J+Vv/AkG7/7trP//7//f/9//7/6/Lr/2uoRv8tjQH/PJYA/zuTAP87kwD/PY8A/z2KAP89hAD/olkn/6RVHP+eSgj/mEgR//Ho3//+/v7/5Ozh/1GaJv8tlAD/OZcC/zuXAv84lAD/O5IC/z2PAf89iwL/OIkA/6hWFf+cTxD/pm9C/76ihP/8/v//+////8nav/8fdwL/NZsA/zeZAP83mgD/PJQB/zyUAf84jwD/PYsB/z6HAf+fXif/1r6s//79///58u//3r+g/+3i2v/+//3/mbiF/yyCAP87mgP/OpgD/zeWAP85lgD/OpEB/z+TAP9ChwH/7eHb/////v/28ej/tWwo/7tUAP+5XQ7/5M+5/////v+bsZn/IHAd/zeVAP89lgP/O5MA/zaJCf8tZTr/DyuK//3////9////0qmC/7lTAP/KZAT/vVgC/8iQWf/+//3///j//ygpx/8GGcL/ESax/xEgtv8FEMz/AALh/wAB1f///f7///z//758O//GXQL/yGYC/8RaAv/Ojlf/+/////////9QU93/BAD0/wAB//8DAP3/AAHz/wAA5f8DAtr///////v7+/+2bCT/yGMA/89mAP/BWQD/0q+D///+/////P7/Rkbg/wEA+f8AA/z/AQH5/wMA8P8AAev/AADf///7/P////7/uINQ/7lXAP/MYwL/vGIO//Lm3P/8/v//1dT2/woM5/8AAP3/AwH+/wAB/f8AAfb/BADs/wAC4P8AAAAA//z7/+LbzP+mXyD/oUwE/9Gshv/8//3/7/H5/zo/w/8AAdX/AgL6/wAA/f8CAP3/AAH2/wAA7v8AAAAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAA==",
                    "http://www.google.com/favicon.ico", 
                    getSearchResultsURL(searchGoogleURL, searchQuery),
                    false                    
                );
            }
            if(config.searchYandex)
            {
                addBubbleLink(
                    "Search Yandex",
                    "http://www.yandex.ru/favicon.ico",
                    getSearchResultsURL(searchYandexURL, searchQuery),
                    true                    
                );
            }
            
            if(config.showHomepageLink)
            {
                var $a = addBubbleLink(
                    "What is this?",
                    "http://static.smarterfox.com/media/img/smarterfox-logo.png",
                    homepageURL
                );
                track_click($a, {name: "homepage_visited", source: config.source});
            }


            var numRows = forceSingleRow ? 1 : Math.floor(Math.sqrt(bubbleLinkAs.length));
            var numCols = Math.ceil(bubbleLinkAs.length / numRows);
            bubbleLinkAs.reverse();
            var a_bubbleLinkA = bubbleLinkAs[0];
            while(bubbleLinkAs.length)
            {
                var $row = $('<span class="smarterwiki-popup-bubble-links-row smarterwiki-clearfix"></span>', doc).prependTo($popupBubbleLinks);
                for(var c = 0; c < numCols; c++)
                {
                    if(bubbleLinkAs.length)
                    {
                        $row.append(bubbleLinkAs.pop());
                    }
                    else
                    {
                        break;
                    }
                }
            }
            
            return $('<span class="smarterwiki-popup-bubble-links-container"></span>', doc).append($popupBubbleLinks);
        };

        var buildPopupSearchBubbleFull = function(config, searchQuery)//, insertCallback)
        {
            var $popupBubble = $(
                '<span class="smarterwiki-popup-bubble smarterwiki-popup-bubble-active"></span>',
                doc
            );
            
            buildPopupSearchBubbleLinks(config, searchQuery, config.forceSingleRow).appendTo(
                $('<span class="smarterwiki-popup-bubble-body"></span>', doc).appendTo($popupBubble)
            );
            

            var $popupBubbleTip = (
                    //config.showHomepageLink ? homepageLink("smarterwiki-popup-bubble-tip") :
                        $('<span class="smarterwiki-popup-bubble-tip"></span>', doc)
                ).appendTo($popupBubble);
                
            //$popupBubble.css("margin-left", "-" + $popupBubble.css("width"));//(3*2 + 3*2 + numCols*18 + (numCols-1)*3)
            //$popupBubble.css("margin-top", "-" + (3*2 + 3*2 + numRows*18 + (numRows-1)*3 + 6) + "px");

            //insertCallback($popupBubble);
            
            //$popupBubble.css("margin-left", "-" + $popupBubble.width() + "px");
            //$popupBubble.css("margin-top", "-" + $popupBubble.height() + "px");

            return $popupBubble;
        };
        //END preview code
        
        var buildPopupSearchBubble = function(searchQuery)//, insertCallback)
        {
            if(!$.browser.msie || ($.browser.msie && $.browser.version.indexOf("8")==0))
            {
                return buildPopupSearchBubbleFull(config, searchQuery);//, insertCallback);
            }
            else
            {//dirty hack for IE
                return buildPopupSearchBubbleLite(config, searchQuery);//, insertCallback); //dirty hack for IE
            }
        };
        
        var get_offsets = function(selection)
        {
            //alert($(".smarterwiki-popup-bubble-active").length);
            //////////////////log_msg_async({name: "popup_bubble_inserted", source: config.source});
            var $test_span = $('<span class="smarterwiki-popup-bubble-test-span">x</span>');//"x" because it must have a height
            try
            {
                var lastRange = getLastRange(selection);
                //$("<div></div>").append(lastRange.cloneContents())[0].innerHTML
                var newRange = doc.createRange();
                newRange.setStart(lastRange.endContainer, lastRange.endOffset);
                newRange.insertNode($test_span[0]);
            }
            catch(err) //dirty hack for IE
            {
                var $tmp = $('<div></div>', doc).append($test_span);
                var newRange = selection.duplicate();
                newRange.setEndPoint("StartToEnd", selection);
                newRange.pasteHTML($tmp[0].innerHTML);
                $test_span = $(".smarterwiki-popup-bubble-test-span");
            }

            var curr_elem = $test_span[0];
            var total_offsetTop = 0;
            var total_offsetLeft = 0;
            while(curr_elem != null)
            {
                total_offsetTop += curr_elem.offsetTop;
                total_offsetLeft += curr_elem.offsetLeft;
                curr_elem = curr_elem.offsetParent;
            }
            $test_span.remove();
            return [total_offsetTop, total_offsetLeft];
        };
        
        var cleanupPopupBubble = function($popupBubble)
        {
            if(!isValidSelection(getSelection(doc)) || 
                !arrayDeepEq($popupBubble.data("selectionKey"), getSelectionKey(getSelection(doc)))
            ) //is this still a valid popup?
            {
                $popupBubble.removeClass("smarterwiki-popup-bubble-active");
                //alert("removing");
                if(config.animate)
                {
                    $popupBubble.stop(true).fadeTo("normal", 0, function() //no longer valid, remove
                    {
                        $popupBubble.remove();
                    });
                }
                else
                {
                    $popupBubble.remove();
                }                
            }
        };


        $(doc).mousedown(function(event)
        {
            //if(isLeftClick(event))
            $(".smarterwiki-popup-bubble", doc).each(function(i)
            {
                cleanupPopupBubble($(this));
            });
        });

        $(doc).mouseup(function(event)
        {
            $(".smarterwiki-popup-bubble", doc).each(function(i)
            {
                cleanupPopupBubble($(this));
            });
            
            get_config(function(conf)
            {
                config = conf;
                if(isLeftClick(event))
                {
                    if(!isDesignMode(doc)) //this can be set after $.ready() :(
                    {
                        var selection = getSelection(doc);
                        if(config.showPopupBubble && isValidSelection(selection))
                        {
                            var shouldInsert = $(".smarterwiki-popup-bubble-active").length == 0;
                            if(shouldInsert)
                            {
                                var queryTerms = selection.toString();
                                var $popupBubble = buildPopupSearchBubble(queryTerms);//, function($popupBubble)
                                var offsets = get_offsets(selection);
                                $("body").append($popupBubble);
                                $popupBubble.data("selectionKey", getSelectionKey(selection), null);
                                
                                var offsetTop = offsets[0];
                                var offsetLeft = offsets[1];
                                $popupBubble.css("top", offsetTop + "px");
                                $popupBubble.css("left", offsetLeft + "px");
                                

                                $popupBubble.css("margin-left", "-" + $popupBubble.css("width"));//(3*2 + 3*2 + numCols*18 + (numCols-1)*3)
                                $popupBubble.css("margin-top", "-" + $popupBubble.css("height"));

                                if(config.animate)
                                {
                                    $popupBubble.css("opacity", 0.0);
                                    if(config.enableGhosting)
                                    {
                                        var ghosted_opacity = 0.25;
                                        $popupBubble.animate({opacity: 1.}, 200)
                                                    .animate({opacity: 1.}, 6000)//.fadeTo("fast", ghosted_opacity)
                                                    .animate({opacity: ghosted_opacity}, 700)//, zIndex: -100000
                                                    .hover(function()//need this because the :hover css doesn't work in quirks mode
                                        {
                                            $popupBubble.stop(true).css("opacity", 1.0);//.css("z-index", 2147483647);
                                        }, function()
                                        {
                                            $popupBubble.stop(true).animate({opacity: ghosted_opacity}, 200);
                                            //.css("opacity", ghosted_opacity).css("z-index", 2147483647);
                                        });                                    
                                    }
                                    else
                                    {
                                        $popupBubble.fadeTo("fast", 1.0);                                    
                                    }
                                }
                                
                                
                                getBoolPref("popup_bubble_show_definitions", function(pref_value)
                                {
                                    if(pref_value)
                                    {
                                        setTimeout(function()
                                        {
                                            get_definition(queryTerms, function(text_html)
                                            {
                                                if(text_html)
                                                {
                                                    $popupBubble.addClass("smarterwiki-popup-bubble-detailed");
                                                    $popupBubble.find(".smarterwiki-popup-bubble-body")
                                                        .empty()
                                                        .append($('<span class="smarterwiki-popup-bubble-definition"></span>')
                                                                    .html(text_html))
                                                        .append(buildPopupSearchBubbleLinks(config, queryTerms, true));
                                                    $popupBubble.css("margin-top", "-" + $popupBubble.css("height"));
                                                    /*
                                                    var width_i = $popupBubble.css("width");
                                                    width_i = width_i.substring(0, width_i.length - 2);
                                                    width_i = parseInt(parseInt(width_i) / 2);
                                                    $popupBubble.css("margin-left", "-" + width_i + "px");//(3*2 + 3*2 + numCols*18 + (numCols-1)*3)
                                                    $popupBubble.find(".smarterwiki-popup-bubble-tip").css("margin-right", width_i + "px !important");
                                                    */
                                                }
                                            });
                                        }, 1200);
                                    }
                                });
                            }
                        }
                    }
                    else
                    {
                        // in rich editor
                    }                    
                }
            });
        });
    };

    var doc = document;
    var blacklist_urlRegExp = new RegExp("https?://(([^/]*\.)?nytimes.com.*)");
    var blacklist_match = blacklist_urlRegExp.exec(doc.location.href);
    if(blacklist_match == null) //ok, add popup bubble
    {
        $(doc).ready(function()
        {
            if(!isDesignMode(doc))
            {
                show_popup_bubble(doc);
            }
            else
            {
                // in rich editor
            }
        });
    }
    else
    {
        // disabled on this page b/c of blacklist
    }
}());