﻿(function () {
    if (typeof (window["util"]) == "undefined") util = {};

    util.getCurrentDir = function () {
        var path = document.location.href;
        return path.substr(0, path.lastIndexOf("/") + 1);
    };

    util.loadScript = function (url, options) {
        var log = window.log;

        try {
            options = $.extend({ async: true, cache: { enabled: true, cachedownloads: true, cacheevals: []} }, options);
            var msg = "loading script '" + url + "': " + JSON.stringify(options) + "...";
            if (log) log.debug("loadscript", msg);

            if (options.cache.enabled) {
                url = util.normalizeUrl(url);
                var same_url = $.grep($("script"), function (script, i) {
                    var type = script.type;
                    var src = util.normalizeUrl(script.src);
                    return type === "text/javascript" && src === url;
                });

                var should_not_download = options.cache.enabled && options.cache.cachedownloads && same_url.length > 0;
                var should_not_eval = options.cache.enabled && options.cache.cacheevals && $.inArray(url, options.cache.cacheevals || []) != -1;
                if (should_not_download || should_not_eval) {
                    var msg = "loading script '" + url + "': already loaded (" + JSON.stringify({ should_not_download: should_not_download, should_not_eval: should_not_eval }) + ").";
                    if (log) log.debug("loadscript", msg);
                    return;
                }
            }

            var success = function () {
                var msg = "loading script '" + url + "': success.";
                if (log) log.debug("loadscript", msg);
                options.cache.cacheevals.push(url);
            };

            if (options.async) {
                var link = document.createElement("script");
                link.type = "text/javascript";
                link.src = url;
                link.onload = success;

                var head = document.getElementsByTagName("head")[0];
                head.appendChild(link);
            } else {
                $.ajax({
                    async: false,
                    type: "GET",
                    url: url,
                    data: null,
                    success: success,
                    cache: options.cache.enabled && options.cache.skipdownload,
                    dataType: 'script'
                });
            }
        } catch (error) {
            var msg = "loading script '" + url + "': " + error ? JSON.stringify(error) : "unknown error" + ".";
            if (log) log.debug("loadscript", msg);
            throw error;
        }
    };

    util.loadStylesheet = function (url, options) {
        var log = window.log;

        try {
            options = $.extend({ async: true, cache: true }, options);
            var msg = "loading stylesheet '" + url + "': " + JSON.stringify(options) + "...";
            if (log) log.debug("loadstylesheet", msg);

            if (options.cache) {
                url = util.normalizeUrl(url);
                var same_url = $.grep($("link"), function (link, i) {
                    var rel = link.rel;
                    var type = link.type;
                    var href = util.normalizeUrl(link.href);
                    return rel === "stylesheet" && type === "text/css" && href === url;
                });

                if (same_url.length > 0) {
                    var msg = "loading stylesheet '" + url + "': already loaded.";
                    if (log) log.debug("loadstylesheet", msg);
                    return;
                }
            }

            var success = function () {
                var msg = "loading stylesheet '" + url + "': success.";
                if (log) log.debug("loadstylesheet", msg);
            };

            if (options.async) {
                var link = document.createElement("link");
                link.rel = "stylesheet";
                link.type = "text/css";
                link.onload = success;
                link.href = url;

                var head = document.getElementsByTagName("head")[0];
                head.appendChild(link);
            } else {
                throw "not supported!";
            }
        } catch (error) {
            var msg = "loading stylesheet '" + url + "': " + error ? JSON.stringify(error) : "unknown error" + ".";
            if (log) log.debug("loadstylesheet", msg);
            throw error;
        }
    };

    util.htmlEncode = function (s) {
        var elm = document.createElement("div");
        elm.innerText = elm.textContent = s;
        s = elm.innerHTML;
        delete elm;
        return s;
    };

    util.urlEncode = function (s) {
        return escape(s);
    };

    util.normalizeUrl = function (url) {
        var startsWith = function (s, prefix) { return s.length >= prefix.length && s.substr(0, prefix.length) === prefix; };
        var endsWith = function (s, postfix) { return s.length >= postfix.length && s.substr(s.length - postfix.length, postfix.length) === postfix; };

        if (!startsWith(url, "http://") && !startsWith(url, "https://") && !startsWith(url, "file:///")) {
            if (startsWith(url, "/")) {
                var root = document.location.protocol + "//" + document.location.host;
                url = root + url;
            } else {
                url = util.getCurrentDir() + url;
            }
        }

        var protocol = startsWith(url, "http://") ? "http://" : startsWith(url, "https://") ? "https://" : startsWith(url, "file:///") ? "file:///" : "";
        url = url.substring(protocol.length);

        url = url.replace(/\\/g, "/");
        while (url.indexOf("//") != -1) url = url.replace(/\/\//g, "/");

        var parts = url.split("/");
        var norm_parts = [];
        $.each(parts, function (i, part) {
            if (part == ".") { } // do nothing
            else if (part == "..") { if (norm_parts.length == 0) throw "invalid path"; else norm_parts.pop(); }
            else { norm_parts.push(part); }
        });

        url = protocol + norm_parts.join("/");
        return url;
    };

    util.getElement = function (el) {
        el = $(el);
        if (el.length) {
            if (el.length == 0) {
                throw "jquery result set is empty";
            } else if (el.length == 1) {
                return el[0];
            } else if (el.length > 1) {
                throw "jquery result set is ambiguous";
            } else {
                throw "jquery error";
            }
        } else {
            throw "jquery error";
        };
    };
})();

