﻿ApplicationLoader = function (settings) {
    document.loader = this;
    this._scripts = null;
    this._types = null;
    this._loadCount = 0;
    this._totalCount = 0;
    this._settings = settings;
    this._queue = [];
    this._currentElement = null;
    this._imgList = [];
    this._loaderID = Math.random();
    this._loadingType = null;
    this._isLoading = false;
    this._loadedTypes = [];
}

ApplicationLoader.CSS = 0;
ApplicationLoader.Script = 1;
ApplicationLoader.Image = 2;
ApplicationLoader.Type = 3;

ApplicationLoader.prototype =
{
    load: function () {
        if (this._isLoading == false) {
            this._isLoading = true;
            this._loadCount = 0;
            this._loadCurrent();
        }
    },

    _isScriptLoaded: function (type) {
        var i = this._loadedTypes.length;
        while (i--) {
            if (this._loadedTypes[i] === type) {
                return true;
            }
        }

        return false;
    },

    loadType: function (typename, callback) {

        if (this._isScriptLoaded(typename) == false) {

            this._loadedTypes.push(typename);
            this._queue.push({ url: typename, type: ApplicationLoader.Type, callback: callback });
            this._totalCount++;
            this.load();
        }
        else if (callback != null) {
            callback();
        }
    },


    loadScript: function (url) {
        var loadUrl = url;
        this._queue.push({ url: loadUrl, type: ApplicationLoader.Script });
        this._totalCount++;
        this.load();
    },

    loadCss: function (url) {
        this._queue.push({ url: url, type: ApplicationLoader.CSS });
        this._totalCount++;
        this.load();
    },

    loadImage: function (url) {
        this._queue.push({ url: url, type: ApplicationLoader.Image });
        this._totalCount++;
        this.load();
    },

    loadCssImages: function () {
        this._loadCssImages(document.styleSheets);
    },

    _loadType: function (item) {

        this._loadingType = item.url;
        var url = item.url + '.mxjs?' + this._loaderID;
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.type = 'text/javascript';
        this._currentElement = script;
        head.appendChild(script);
        script.src = url;
        script._readyCallback = item.callback;
        this._checkTypeLoaded();
    },

    _checkTypeLoaded: function () {
        try {
            var c = eval(document.loader._loadingType);
            if (c == null) {
                throw new Error();
            }
        }
        catch (e) {
            setTimeout(document.loader._checkTypeLoaded, 50);
            return;
        }

        ApplicationLoader._loadingType = null;
        document.loader._onItemComplete();
    },

    _loadScript: function (url) {

        if (url != null) {
            var _this = this;
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('script');
            script.type = 'text/javascript';
            this._currentElement = script;
            if (document.all) {
                script.onreadystatechange = this._loaded;
            }
            else {
                script.onload = this._loaded;
            }

            head.appendChild(script);
            script.src = url;
        }
    },

    _loadImage: function (url) {
        if (url != null) {
            var _this = this;
            var element = document.createElement('img');
            element.style.width = '100px';
            element.src = url;
            this._imgList.push(element);
            this._currentElement = element;

            var img = new Image()
            img.src = url;

            if (img.complete == true) {
                this._onItemComplete();
            }
            else {
                img.onload = this._loaded;
            }
        }
    },

    _loadCss: function (url) {
        if (url != null) {
            var _this = this;
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('link');
            script.rel = 'stylesheet';
            script.type = 'text/css';
            this._currentElement = script;
            if (document.all) {
                script.onreadystatechange = this._cssLoaded;
            }
            else {
                shCount = document.styleSheets.length;
                setTimeout(document.loader._cssLoadedHack, 50);
            }

            head.appendChild(script);
            script.href = url;
        }

    },

    _loadCurrent: function () {
        this._isLoading = true;
        var item = this._queue.splice(0, 1)[0];
        var url = item.url;

        switch (item.type) {
            case ApplicationLoader.Script:
                this._loadScript(url);
                break;

            case ApplicationLoader.CSS:
                this._loadCss(url);
                break;

            case ApplicationLoader.Image:
                this._loadImage(url);
                break;

            case ApplicationLoader.Type:

                this._loadType(item);
                break;
        }

    },

    get_currentName: function () {

        switch (this._currentElement.tagName) {
            case 'LINK':
                return 'Loading theme';
                break;


            case 'IMG':
                return 'Loading images';
                break;

            case 'SCRIPT':
                return 'Loading assemblies';
                break;
        }
    },

    _onItemComplete: function () {
        var name = this.get_currentName();
        var cb = this._currentElement._readyCallback;

        if (cb != null) {

            cb();
        }

        this._currentElement = null;
        this._loadCount++;
        if (this._settings.load != null) {
            this._settings.load(name, this._loadCount, this._totalCount);
        }

        if (this._queue.length > 0) {
            this._loadCurrent();
        }
        else {
            this._onComplete();
        }
    },

    _onComplete: function () {
        this._isLoading = false;
        if (this._settings.load_all != null) {
            this._settings.load_all();
        }

        this._loadCount = 0;
        this._totalCount = 0;
    },

    _loaded: function () {

        if (!(document.all) || this.readyState == 'loaded' || this.readyState == 'complete') {
            var l = document.loader;
            this.onreadystatechange = null;
            this.onload = null;
            l._onItemComplete();
        }

    },

    _loadCssImages: function (stylesheets) {
        var l = document.loader;
        var images = l._parseCSS(stylesheets);
        for (var i in images) {
            var url = images[i];
            l.loadImage(url);
        }
    },

    _cssLoaded: function () {
        if (!(document.all) || this.readyState == 'loaded' || this.readyState == 'complete') {
            var l = document.loader;
            this.onreadystatechange = null;
            this.onload = null;
            l._loadCssImages([this.styleSheet]);
            l._onItemComplete();
        }
    },

    _cssLoadedHack: function () {
        var sh = document.styleSheets[shCount];
        var rules = null;

        try {
            rules = sh.rules || sh.cssRules;
        }
        catch (e) {

        }


        if (rules == null) {

            setTimeout(document.loader._cssLoadedHack, 50);
        } else {
            var l = document.loader;
            l._loadCssImages(sh);
            l._onItemComplete();
        }

    },

    _containsUrl: function (a, obj) {
        var i = a.length;
        while (i--) {
            if (a[i] === obj) {
                return true;
            }
        }

        return false;
    },

    _parseCSS: function (sheets, urls, imgUrls) {
        if (imgUrls == null) {
            imgUrls = [];
        }
        var w3cImport = false,
			imported = [],
			importedSrc = [],
			baseURL;
        var sheetIndex = sheets.length;
        while (sheetIndex--) {//loop through each stylesheet

            var cssPile = ''; //create large string of all css rules in sheet

            if (urls && urls[sheetIndex]) {
                baseURL = urls[sheetIndex];
            } else {
                var csshref = (sheets[sheetIndex].href) ? sheets[sheetIndex].href : 'window.location.href';
                var baseURLarr = csshref.split('/'); //split href at / to make array
                baseURLarr.pop(); //remove file path from baseURL array
                baseURL = baseURLarr.join('/'); //create base url for the images in this sheet (css file's dir)
                if (baseURL) {
                    baseURL += '/'; //tack on a / if needed
                }
            }
            if (sheets[sheetIndex].cssRules || sheets[sheetIndex].rules) {
                thisSheetRules = (sheets[sheetIndex].cssRules) ? //->>> http://www.quirksmode.org/dom/w3c_css.html
					sheets[sheetIndex].cssRules : //w3
					sheets[sheetIndex].rules; //ie 
                var ruleIndex = thisSheetRules.length;
                while (ruleIndex--) {
                    if (thisSheetRules[ruleIndex].style && thisSheetRules[ruleIndex].style.cssText) {
                        var text = thisSheetRules[ruleIndex].style.cssText;
                        if (text.toLowerCase().indexOf('url') != -1) { // only add rules to the string if you can assume, to find an image, speed improvement
                            cssPile += text; // thisSheetRules[ruleIndex].style.cssText instead of thisSheetRules[ruleIndex].cssText is a huge speed improvement
                        }
                    } else if (thisSheetRules[ruleIndex].styleSheet) {
                        imported.push(thisSheetRules[ruleIndex].styleSheet);
                        w3cImport = true;
                    }

                }
            }
            //parse cssPile for image urls
            var tmpImage = cssPile.match(/[^\("]+\.(gif|jpg|jpeg|png)/g); //reg ex to get a string of between a "(" and a ".filename" / '"' for opera-bugfix
            if (tmpImage) {
                var i = tmpImage.length;
                while (i--) { // handle baseUrl here for multiple stylesheets in different folders bug
                    var imgSrc = (tmpImage[i].charAt(0) == '/' || tmpImage[i].match('://')) ? // protocol-bug fixed
						tmpImage[i] :
						baseURL + tmpImage[i];
                    if (this._containsUrl(imgUrls, imgSrc) == false) {
                        imgUrls.push(imgSrc);
                    }

                }
            }

            if (!w3cImport && sheets[sheetIndex].imports && sheets[sheetIndex].imports.length) {
                for (var iImport = 0, importLen = sheets[sheetIndex].imports.length; iImport < importLen; iImport++) {
                    var iHref = sheets[sheetIndex].imports[iImport].href;
                    iHref = iHref.split('/');
                    iHref.pop();
                    iHref = iHref.join('/');
                    if (iHref) {
                        iHref += '/'; //tack on a / if needed
                    }
                    var iSrc = (iHref.charAt(0) == '/' || iHref.match('://')) ? // protocol-bug fixed
						iHref :
						baseURL + iHref;

                    importedSrc.push(iSrc);
                    imported.push(sheets[sheetIndex].imports[iImport]);
                }


            }
        } //loop
        if (imported.length) {
            parseCSS(imported, importedSrc, imgUrls);
            return false;
        }
        return imgUrls;

    }


}
