(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "../App", "../core/AtomOnce", "../core/AtomUri", "../di/ServiceCollection", "../services/BusyIndicatorService", "../services/NavigationService", "./core/AtomUI", "./services/WebBusyIndicatorService", "./services/WindowService", "./styles/AtomStyleSheet", "./styles/AtomTheme"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    const App_1 = require("../App");
    const AtomOnce_1 = require("../core/AtomOnce");
    const AtomUri_1 = require("../core/AtomUri");
    const ServiceCollection_1 = require("../di/ServiceCollection");
    const BusyIndicatorService_1 = require("../services/BusyIndicatorService");
    const NavigationService_1 = require("../services/NavigationService");
    const AtomUI_1 = require("./core/AtomUI");
    const WebBusyIndicatorService_1 = require("./services/WebBusyIndicatorService");
    const WindowService_1 = require("./services/WindowService");
    const AtomStyleSheet_1 = require("./styles/AtomStyleSheet");
    const AtomTheme_1 = require("./styles/AtomTheme");
    class WebApp extends App_1.App {
        constructor() {
            super();
            this.mContextId = 1;
            this.hashUpdater = new AtomOnce_1.AtomOnce();
            this.url = new AtomUri_1.AtomUri(location.href);
            this.put(NavigationService_1.NavigationService, this.resolve(WindowService_1.WindowService));
            this.put(WebApp, this);
            this.put(BusyIndicatorService_1.BusyIndicatorService, this.resolve(WebBusyIndicatorService_1.WebBusyIndicatorService));
            ServiceCollection_1.ServiceCollection.instance.registerSingleton(AtomStyleSheet_1.AtomStyleSheet, (sp) => sp.resolve(AtomTheme_1.AtomTheme));
            // let us set contextId
            this.mContextId = parseInt((this.url.hash.contextId || "0").toString(), 10);
            if (!this.mContextId) {
                //  create new context Id in session...
                for (let index = 0; index < 100; index++) {
                    const cid = `contextId${index}`;
                    const cidData = sessionStorage.getItem(`contextId${index}`);
                    if (!cidData) {
                        this.mContextId = index;
                        sessionStorage.setItem(cid, cid);
                        this.url.hash.contextId = index;
                        this.syncUrl();
                        break;
                    }
                }
            }
            window.addEventListener("hashchange", () => {
                this.hashUpdater.run(() => {
                    this.url = new AtomUri_1.AtomUri(location.href);
                });
            });
            // following must be done automatically by the user as we may need different and newer version
            // // registering font awesome
            // this.installStyleSheet("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.9.0/css/all.css");
            // this.installStyleSheet({
            //     href: "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css",
            //     integrity: "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T",
            //     crossOrigin: "anonymous"
            // });
        }
        get parentElement() {
            return document.body;
        }
        get root() {
            return this.mRoot;
        }
        set root(v) {
            const old = this.mRoot;
            if (old) {
                old.dispose();
            }
            this.mRoot = v;
            if (!v) {
                return;
            }
            const pe = this.parentElement;
            const ce = new AtomUI_1.ChildEnumerator(pe);
            const de = [];
            while (ce.next()) {
                const current = ce.current;
                de.push(current);
            }
            for (const iterator of de) {
                iterator.remove();
            }
            pe.appendChild(v.element);
        }
        get theme() {
            return this.get(AtomStyleSheet_1.AtomStyleSheet);
        }
        set theme(v) {
            this.put(AtomTheme_1.AtomTheme, v);
            this.put(AtomStyleSheet_1.AtomStyleSheet, v);
        }
        get contextId() {
            return `contextId_${this.mContextId}`;
        }
        installStyleSheet(ssConfig) {
            if (typeof ssConfig !== "object") {
                ssConfig = { href: ssConfig };
            }
            ssConfig.href = UMD.resolvePath(ssConfig.href);
            const links = document.getElementsByTagName("link");
            // tslint:disable-next-line:prefer-for-of
            for (let index = 0; index < links.length; index++) {
                const element = links[index];
                const href = element.getAttribute("href");
                if (href === ssConfig.href) {
                    return;
                }
            }
            const ss = document.createElement("link");
            ss.rel = "stylesheet";
            ss.href = ssConfig.href;
            if (ssConfig.crossOrigin) {
                ss.crossOrigin = ssConfig.crossOrigin;
            }
            if (ssConfig.integrity) {
                ss.integrity = ssConfig.integrity;
            }
            document.head.appendChild(ss);
        }
        installScript(location) {
            location = UMD.resolvePath(location);
            const links = document.getElementsByTagName("script");
            // tslint:disable-next-line:prefer-for-of
            for (let index = 0; index < links.length; index++) {
                const element = links[index];
                const href = element.getAttribute("src");
                if (href === location) {
                    return element.loaderPromise;
                }
            }
            const script = document.createElement("script");
            const p = new Promise((resolve, reject) => {
                script.type = "text/javascript";
                script.src = location;
                const s = script;
                script.onload = s.onreadystatechange = () => {
                    if ((s.readyState && s.readyState !== "complete" && s.readyState !== "loaded")) {
                        return;
                    }
                    script.onload = s.onreadystatechange = null;
                    resolve();
                };
                document.body.appendChild(script);
            });
            script.loaderPromise = p;
            return p;
        }
        updateDefaultStyle(textContent) {
            if (this.styleElement) {
                if (this.styleElement.textContent === textContent) {
                    return;
                }
            }
            const ss = document.createElement("style");
            ss.textContent = textContent;
            if (this.styleElement) {
                this.styleElement.remove();
            }
            document.head.appendChild(ss);
            this.styleElement = ss;
        }
        /**
         * Do not use this method
         */
        syncUrl() {
            this.hashUpdater.run(() => {
                const currentUrl = new AtomUri_1.AtomUri(location.href);
                const sourceHash = this.url.hash;
                const keyValues = [];
                let modified = false;
                for (const key in sourceHash) {
                    if (/^\_\$\_/.test(key)) {
                        continue;
                    }
                    if (sourceHash.hasOwnProperty(key)) {
                        const element = sourceHash[key];
                        const cv = currentUrl.hash[key];
                        if (element !== undefined) {
                            keyValues.push({ key, value: element });
                        }
                        if (cv === element) {
                            continue;
                        }
                        modified = true;
                    }
                }
                if (!modified) {
                    return;
                }
                const hash = keyValues.map((s) => `${s.key}=${encodeURIComponent(s.value)}`).join("&");
                location.hash = hash;
            });
        }
        invokeReady() {
            if (document.readyState === "complete") {
                super.invokeReady();
                return;
            }
            document.addEventListener("readystatechange", (e) => {
                super.invokeReady();
            });
        }
    }
    exports.default = WebApp;
    // tslint:disable-next-line: only-arrow-functions
    (function () {
        if (typeof window.CustomEvent === "function") {
            return false;
        }
        function CustomEvent(event, params) {
            params = params || { bubbles: false, cancelable: false, detail: null };
            const evt = document.createEvent("CustomEvent");
            evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
            return evt;
        }
        window.CustomEvent = CustomEvent;
    })();
});
//# sourceMappingURL=WebApp.js.map