
window.AScript = new Map();
window.isTouchAvailable = 'ontouchstart' in window ||
    window.DocumentTouch && document instanceof window.DocumentTouch ||
    navigator.maxTouchPoints > 0 ||
    window.navigator.msMaxTouchPoints > 0

if (Node.prototype.appendChildren === undefined) {
    Node.prototype.appendChildren = function () {
        let children = [...arguments];

        if (
            children.length == 1 &&
            Object.prototype.toString.call(children[0]) === "[object Array]"
        ) {
            children = children[0];
        }
        var documentFragment = document.createDocumentFragment();
        children.forEach(c => documentFragment.appendChild(c));
        this.appendChild(documentFragment);
    };
}
if (Node.prototype.removeAll === undefined) {
    Node.prototype.removeAll = function () {
        while (this.firstChild) this.removeChild(this.lastChild);
    };
}
if (NodeList.prototype.removeAll === undefined) {
    NodeList.prototype.removeAll = function () {
        for (var i = this.length - 1; i >= 0; i--) {
            this[i].remove();
        }
    };
}

if (Array.prototype.hasItem === undefined) {
    Array.prototype.hasItem = function (o, callback) {
        var f = false;
        this.forEach(e => {
            if (callback(e, o)) {
                f = true;
                return;
            }
        });
        return f;
    }
}

if (Array.prototype.removeItem === undefined) {
    Array.prototype.removeItem = function (o, callback) {
        var f = false;
        this.forEach((e, i) => {
            if (callback(e, o)) {
                delete this[i];
                this.splice(i, 1);
            }
        });
        return f;
    }
}

window.getOS = function () {
    var userAgent = window.navigator.userAgent,
        platform = window.navigator.platform,
        macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'],
        windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'],
        iosPlatforms = ['iPhone', 'iPad', 'iPod'],
        os = null;

    if (macosPlatforms.indexOf(platform) !== -1) {
        os = 'Mac OS';
    } else if (iosPlatforms.indexOf(platform) !== -1) {
        os = 'iOS';
    } else if (windowsPlatforms.indexOf(platform) !== -1) {
        os = 'Windows';
    } else if (/Android/.test(userAgent)) {
        os = 'Android';
    } else if (!os && /Linux/.test(platform)) {
        os = 'Linux';
    }

    return os;
}

window.GetAbsoluteURL = function (relativeURL) {
    return window.location.origin + relativeURL;
}

window.GetEventType = function () {
    if (isTouchAvailable) {
        return "touchend";
    } else {
        return "click";
    }
}
window.fireEvent = function (element, event) {
    if (document.createEventObject) {
        // dispatch for IE
        var evt = document.createEventObject();
        return element.fireEvent('on' + event, evt)
    }
    else {
        // dispatch for firefox + others
        var evt = document.createEvent("HTMLEvents");
        evt.initEvent(event, true, true); // event type,bubbling,cancelable
        return !element.dispatchEvent(evt);
    }
}
window.requestTimeout = function (fn, delay, registerCancel = () => { }) {
    const start = new Date().getTime();

    const loop = () => {
        const delta = new Date().getTime() - start;

        if (delta >= delay) {
            fn();
            registerCancel(function () { });
            return;
        }

        const raf = requestAnimationFrame(loop);
        registerCancel(() => cancelAnimationFrame(raf));
    };

    const raf = requestAnimationFrame(loop);
    registerCancel(() => cancelAnimationFrame(raf));
};



window.formatDateToString = function (date) {
    var dd = (date.getDay() < 10 ? '0' : '') + date.getDay();
    var MM = ((date.getMonth() + 1) < 10 ? '0' : '') + (date.getMonth() + 1);
    var yyyy = date.getFullYear();
    var hh = (date.getHours() < 10 ? '0' : '') + date.getHours();
    var mm = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
    var ss = (date.getSeconds() < 10 ? '0' : '') + date.getSeconds();
    return (dd + "-" + MM + "-" + yyyy + " " + hh + ":" + mm + ":" + ss);
}
window.padLeadingZeros = function (num, size) {
    var s = num + "";
    while (s.length < size) s = "0" + s;
    return s;
}
window.AddFormData = function (frm, name, val) {
    if (frm.has(name)) {
        frm.set(name, val); v
    } else {
        frm.append(name, val);
    }
}

window.checkViewHeight = function () {
    let vh = window.innerHeight * 0.01;
    document.documentElement.style.setProperty('--vh', `${vh}px`);
}
window.checkViewHeight();
window.addEventListener('resize', () => {
    window.checkViewHeight();
});
window.AObject = class {
    constructor() {
        this.listeners = new Map();
        this.onceListeners = new Map();
        this.triggerdLabels = new Map();
        this.stackEvent = Array.from([]);
    }

    // help-function for onReady and onceReady
    // the callbackfunction will execute, 
    // if the label has already been triggerd with the last called parameters
    _fCheckPast(label, callback) {
        if (this.triggerdLabels.has(label)) {
            callback(this.triggerdLabels.get(label));
            return true;
        } else {
            return false;
        }
    }

    // execute the callback everytime the label is trigger
    on(label, callback, checkPast = false) {
        this.listeners.has(label) || this.listeners.set(label, []);
        this.listeners.get(label).push(callback);
    
        if (checkPast)
            this._fCheckPast(label, callback);
      
    }

    // execute the callback everytime the label is trigger
    // check if the label had been already called 
    // and if so excute the callback immediately
    onReady(label, callback) {
        this.on(label, callback, true);
    }

    // execute the callback onetime the label is trigger
    once(label, callback, checkPast = false) {
        this.onceListeners.has(label) || this.onceListeners.set(label, []);
        if (!(checkPast && this._fCheckPast(label, callback))) {
            // label wurde nocht nicht aufgerufen und 
            // der callback in _fCheckPast nicht ausgeführt
            this.onceListeners.get(label).push(callback);
        }
    }
    // execute the callback onetime the label is trigger
    // or execute the callback if the label had been called already
    onceReady(label, callback) {
        this.once(label, callback, true);
    }

    // remove the callback for a label
    off(label, callback = true) {
        if (callback === true) {
            // remove listeners for all callbackfunctions
            this.listeners.delete(label);
            this.onceListeners.delete(label);
        } else {
            // remove listeners only with match callbackfunctions
            let _off = (inListener) => {
                let listeners = inListener.get(label);
                if (listeners) {
                    inListener.set(label, listeners.filter((value) => !(value === callback)));
                }
            };
            _off(this.listeners);
            _off(this.onceListeners);
        }
    }

    // trigger the event with the label 
    trigger(label, ...args) {
        let res = false;
        this.triggerdLabels.set(label, ...args); // save all triggerd labels for onready and onceready
        let _trigger = (inListener, label, ...args) => {
            let listeners = inListener.get(label);
            if (listeners && listeners.length) {
                listeners.forEach((listener) => {

                    listener(...args);
                });
                res = true;
            }
        };
        _trigger(this.onceListeners, label, ...args);
        _trigger(this.listeners, label, ...args);
        this.onceListeners.delete(label); // callback for once executed, so delete it.
        return res;
    }
    dispose() {
        for (var i = this.stackEvent.length - 1; i >= 0; i -= 1) {
            var e = this.stackEvent[i];
            e.element.removeEventListener(e.event, e.callback, false);
            this.stackEvent.splice(i, 1);
        }
    }
    //this.stackEvent.push({ "event": "click", "callback": k, "element": c, "parent": null });
    removeEvent(a) {
        for (var i = this.stackEvent.length - 1; i >= 0; i -= 1) {
            var e = this.stackEvent[i];
            if (e.element == a) {
                e.element.removeEventListener(e.event, e.callback, false);
                this.stackEvent.splice(i, 1);
                break;
            }
        }
    }
    removeEventParent(a) {
        for (var i = this.stackEvent.length - 1; i >= 0; i -= 1) {
            var e = this.stackEvent[i];
            if (e.parent == a) {
                e.element.removeEventListener(e.event, e.callback, false);
                this.stackEvent.splice(i, 1);
                break;
            }
        }
    }
    removeAllChildNodes(parent) {
        while (parent.firstChild) {
            parent.removeChild(parent.firstChild);
        }
    }
    cloneNodes(elmS, elmD) {
        var childs = elmS.childNodes;
        for (var i = 0; i < childs.length; i++) {
            elmD.appendChild(childs[i].cloneNode(true));
        }
    }
}
class LoadScriptAsync extends window.AObject {
    constructor(type) {
        super();
        this.type = type;
        this.listCurrent = new Map();
        this.stackScript = [];
        this.jsLib = document.querySelector("section[app-js-lib]");
        this.jsPage = document.querySelector("section[app-js-page]");
        this.count = 0;
    }
    getScripts() {
        document.querySelectorAll("section [js-lib]").forEach(el => {

            if (!el.hasAttribute("checked")) {
                this.listCurrent.set(el.src.split(/(\\|\/)/g).pop(), { "el": el.src, "status": "0" });
                el.setAttribute("checked", "");
            }
        });
    }
    processScript(doc) {
        if (typeof doc.childNodes === "undefined") {
            return;
        }
        this.stackScript = [];
        this.listCurrent = new Map();
        this.getScripts();
        for (var i = 0; i < doc.childNodes.length; i++) {
            var n = doc.childNodes[i];
            if (n.getAttribute("js-page") != null) {
                this.stackScript.push({ "el": n });
            }
            if (n.getAttribute("js-lib") != null) {
                if (this.checkExist(n)) {
                    continue;
                }
                var src = n.getAttribute("src");
                this.jsLib.appendChild(this.createScriptTag(n));
                this.listCurrent.set(src.split(/(\\|\/)/g).pop(), { "el": src, "status": "0" });
            }
        }

        window.requestTimeout(this.checkLoaded.bind(this), 10, window.registerCancel);
    }
    checkLoaded(depend) {
        this.listCurrent.forEach((v, k, m) => {
            var tn = k.substring(0, k.length - 3);
            if (window.AScript.has(tn)) {
                this.listCurrent.delete(k);
            }
        });
        if (this.listCurrent.size == 0) {
            this.addJsPage();
            this.trigger("Loaded", null);
        } else {
            window.requestTimeout(this.checkLoaded.bind(this), 10, window.registerCancel);
        }
    }
    checkExist(elm) {
        if (this.listCurrent.has(elm.src.split(/(\\|\/)/g).pop())) {
            return true;
        } else {
            return false;
        }
    }
    createScriptTag(el) {
        var newScript = document.createElement("script");
        newScript.setAttribute("async", "");
        for (var i = 0; i < el.attributes.length; i++) {
            newScript.setAttribute(el.attributes[i].name, el.attributes[i].value);
        }
        if (!el.hasChildNodes()) {
            newScript.src = el.src;
        } else {
            var tmp = document.createTextNode(el.innerHTML);
            newScript.appendChild(tmp);
        }
        return newScript;
    }
    addJsPage() {
        this.jsPage.innerHTML = "";
        if (window.Destroy != undefined) window.Destroy();
        this.stackScript.forEach(el => {
            this.jsPage.appendChild(this.createScriptTag(el.el));

        });
    }
}
class AApp extends window.AObject {
    constructor(container = '[app-content]') {
        super();
        this.listScripts = [];
        this.cachePage = [];
        this.isLoadedLayout = false;
        window.Destroy = undefined;
        this.isRedirectPage = false;
        this.metaPage = document.head.querySelector("meta[name=idPage]");
        this.pageName = this.metaPage.getAttribute("pageName");
        this.isDispLay = this.metaPage.getAttribute("isLayout");
        var tmp = document.querySelector(container);
        this.mainApp = tmp.querySelector("[main-content]") ? tmp.querySelector("[main-content]") : tmp;
        var f = function (ev) {
            if (ev.state) {
                var temp = document.createElement("template");
                temp.innerHTML = ev.state.html;
                this.loadContentPage(temp.content);
                this.metaPage.content = ev.state.idPage;
                this.metaPage.setAttribute("isLayout", ev.state.isLayout);
                this.trigger("redirect_page", ev.state);
                this.checkLayout(ev.state.isLayout);
                var l = new LoadScriptAsync("Page");
                var oP = new DOMParser();
                l.processScript(oP.parseFromString(ev.state.doc, 'text/html').head);
                l.on("Loaded", () => {
                 
                    this.loadedPage(false);
                });
            }
        }.bind(this);
        window.addEventListener("popstate", f);
    }
    checkLayout(isLayout) {
        if ((this.isDispLay && isLayout) == false) {
            // display = false -> layout true
            console.log("Run");
            if (isLayout) {
                if (window.isLoad_Menu) {
                    window.Show_Menu();
                } else {
                    this.renderLayout();
                }
            } else    /*display =true -> layout false */ {
                window.Hide_Menu();
            }
               
     
        }
        this.isDispLay = isLayout;
    }
    render() {
        if (this.isDispLay) {
            this.renderLayout();
        } else {
            this.isLoadedLayout = true;
        }
        this.renderNoLayout();
    }
    renderNoLayout() {
        (function () {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", window.location.href + "?vr=cAsync");
            xhr.send();
            var f = function (evt) {
                if (evt.currentTarget.readyState == 4 && evt.currentTarget.status == 200) {
                    if (evt.currentTarget.responseText) {
                        var jP = JSON.parse(evt.currentTarget.responseText);
                        this.loadPage(jP, window.location.href);
                    }
                }
            }.bind(this);
            xhr.addEventListener("readystatechange", f, false);
        }).bind(this)();
    }
    renderLayout() {
        (function () {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", window.location.href + "?vr=lAsync");
            xhr.send();
            var f = function (evt) {
                if (evt.currentTarget.readyState == 4 && evt.currentTarget.status == 200) {
                    if (evt.currentTarget.responseText) {
                        var jP = JSON.parse(evt.currentTarget.responseText);
                        this.loadLayout(jP, window.location.href);
                    }
                }
            }.bind(this);
            xhr.addEventListener("readystatechange", f, false);
        }).bind(this)();
    }
    loadedPage() {
        this.metaPage = document.head.querySelector("meta[name=idPage]");
        if (this.metaPage != null && this.isLoadedLayout) {
            if (window["L" + this.metaPage.content] != null) {
                window["L" + this.metaPage.content]();
            }
           
            this.initNavs();
            this.trigger("pageLoaded", null);
        } else {
            window.requestTimeout(this.loadedPage.bind(this), 10, window.registerCancel);
        }
    }
    loadedLayout() {
        if (!window.isLoad_Menu) {
            window.Load_Menu();
            this.isLoadedLayout = true;
        }
        this.trigger("layoutLoaded", null);
    }
    scrollTop() {
        return window.scrollY || window.smScroll.scrollTop;
    }
    checkVisible(elm) {
        var rect = elm.getBoundingClientRect();
        var viewHeight = window.innerHeight;
        return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
    }
    initScrollBar() {
        if (window.getOS() == "iOS") {
            document.querySelector(".main-scrollbar[data-scrollbar]").classList.add("iOS");
            let scrollY = 0;
            let ticking = false;

            window.addEventListener('scroll', ((event) => {
                scrollY = window.scrollY;

                if (!ticking) {
                    window.requestAnimationFrame(() => { 
                        this.trigger("App_Scrolling", scrollY);
                        ticking = false;
                    });
                    ticking = true;
                }
               
            }).bind(this));
        } else {
           
            var sOption = {
                damping: (window.getOS() == "Android")?.1:.04,
                thumbMinSize: 25,
                renderByPixel: true,
                alwaysShowTracks: true,
                continuousScrolling: true,
                plugins: {
                    overscroll: {
                        effect: 'bounce',
                        damping: .15,//0.15
                        maxOverscroll: 250
                    }
                }
            };
            window.smScroll = window.Scrollbar.init(document.querySelector('.main-scrollbar[data-scrollbar]'), sOption);
            window.smScroll.addListener((status => {
                this.trigger("App_Scrolling", status.offset.y);
            }).bind(this));
        }
    }
    initNavs() {
        document.querySelectorAll("[app-nav][app-url]").forEach(((el) => {
            if (el.getAttribute("app-nav") != true) {
                el.addEventListener("click", ((ev) => {
                    this.initNavApp(ev.currentTarget);
                }).bind(this));
                el.setAttribute("app-nav", true);
            }
        }).bind(this));
    }
    initNavApp(t) {
        this.isRedirectPage = true;
        this.callLoadPage(t.getAttribute("app-url"));
    }
    callLoadPage(url) {
        var f = true;
        var page = null;
        for (var i = 0; i < this.cachePage.length; i++) {
            if (this.cachePage[i].src == url) {
                f = false;
                page = this.cachePage[i];
                break;
            }
        }
        if (f) {
            this.getPage(url);
        } else {
            var tpl = document.createElement('template');
            tpl.innerHTML = page.html;
            this.setContentPage(Object.assign({}, page, { "html": tpl.content }));
        }
    }
    loadContentPage(content) {
        for (var i = this.mainApp.childNodes.length - 1; i >= 0; i--) {
            this.mainApp.childNodes[i].remove();
        }
        this.mainApp.appendChild(content);
    }
    setContentPage(page) {
        document.title = page.title + " - " + this.pageName;
        var meta = document.head.querySelector("meta[name=idPage]");
        meta.content = page.idPage;

        this.checkLayout(page.isLayout);
        meta.setAttribute("isLayout", page.isLayout);
       
        this.loadContentPage(page.html);
        window.history.pushState({ "html": this.mainApp.innerHTML, "doc": page.doc.innerHTML, "idPage": page.idPage, "isLayout": page.isLayout }, page.title , page.src);
        var l = new LoadScriptAsync("Page");
        if (this.isRedirectPage) {
            this.trigger("redirect_page", page);
            this.isRedirectPage = false;
        }
        l.on("Loaded", () => {
            this.loadedPage(false);
        });
        l.processScript(page.doc);

    }
    getPage(url) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url + "?vr=cAsync");
        xhr.send();
        var f = function (evt) {
            if (evt.currentTarget.readyState == 4 && evt.currentTarget.status == 200) {
                if (evt.currentTarget.responseText) {
                    var jP = JSON.parse(evt.currentTarget.responseText);
                    this.loadPage(jP, url);
                }
            }
        }.bind(this);
        xhr.addEventListener("readystatechange", f, false);
    }
    loadLayout(o, url) {
        var oP = new DOMParser();
        var pHtml = oP.parseFromString(o.Content, 'text/html');
        (function () {
            pHtml.body.childNodes.forEach(function (item) {
                var t = document.getElementById(item.getAttribute("id"));
                if (t) {
                    item.classList.forEach(el => {
                        t.classList.add(el);
                    });
                    item.childNodes.forEach(el => {
                        t.appendChild(el.cloneNode(true));
                    });
                }
            });
        }).bind(this)();
        (function () {
            var doc = oP.parseFromString(o.Scripts, 'text/html').head;
            var l = new LoadScriptAsync("Layout");
            l.on("Loaded", () => {
                this.loadedLayout();
            });
            l.processScript(doc);
        }).bind(this)();
    }
    loadPage(o, url) {
            var title = o.Title;
            var idPage = o.PageId;
            var tpl = document.createElement('template');
        tpl.innerHTML = o.Content;
            var doc2 = new DOMParser().parseFromString(o.Scripts, "text/html");
            var obj = { "src": url, "html": o.Content, "title": title, "idPage": idPage, "doc": doc2.firstChild.querySelector("head"), "isLayout": o.IsDisLayout };
            this.cachePage.push(obj);
            this.setContentPage(Object.assign({}, obj, { "html": tpl.content }));
    }
    loadCSS(arr) {
        for (var i = 0; i < arr.length; i++) {
            var link = document.createElement('link');
            link.setAttribute('rel', 'stylesheet');
            link.setAttribute('href', arr[i]);
            document.head.appendChild(link);
        }
    }
}

window.removeStopCollapsed = function () {
    if (window.dropdown != null && window.dropdown.currentE != null) {
        if (window.dropdown.currentE.item.hasAttribute("stopCollapsed")) {
            window.dropdown.currentE.item.removeAttribute("stopCollapsed");
            window.dropdown.currentE = null;
        }
    }
}
window.scroll_options = {
    damping: 0.1,
    thumbMinSize: 25,
    renderByPixel: true,
    alwaysShowTracks: true,
    continuousScrolling: true,
    plugins: {
        overscroll: {
            effect: 'bounce',
            damping: 0.15,
            maxOverscroll: 150
        }
    }
};