var STORAGE_ID_SCHEME = "appclient-scheme",
    STORAGE_ID_LANG = "appclient-lang",
    STORAGE_ID_CONFIG = "appclient-config",
    startSchemes = {
        "dark": {
            "--client-bg1": "#232323", 			  // AppClient BG
            "--client-bg2": "#161616", 			  // AppClient Header-BG
            "--forms": "#1E1E1E", 				  // for searchbar
            "--bg1": "#282828", 				  // background level 1, f.e. Main-BG
            "--bg2": "#333333", 				  // background level 2, f.e. Header-BG
            "--bg3": "#474747", 				  // background level 3, f.e. Panel-BG
            "--c1": "#efefef", 					  // main text color
            "--c2": "#939393", 					  // darker text color, f.e. for less important text
            "--button-bg": "#3D3D3D", 			  // used only for buttons
            "--red": "#ef4d64", 				  // used f.e. for missed-calls-Icon, end-call-Icon or delete-Buttons
            "--green": "#7cb270", 				  // used f.e. for call-icon or confirm-buttons
            "--yellow": "#f59b10", 				  // used for special highlighting
            "--white": "#ffffff",
            "--placeholder-bg": "#5f5f5f",
            "--placeholder-c": "#c3c3c3",
            "--badge-bg": "#f44336",
            "--badge-c": "#ffffff",
            "--transparent-bg1": "rgba(0,0,0,0.7)",
            "--transparent-bg2": "rgba(0,0,0,0.4)",
            "--logo-c0": "#ffffff",               // text
            "--logo-c1": "#808080",               // neutral color (--white)
            "--logo-c2": "#17baae",               // green (--yellow from light scheme)
            "--logo-c3": "#f59b10",               // orange (--yellow from dark scheme)
            "--watermark-c": "#202020",
            "--radius": "16px"
        },
        "light": {
            "--client-bg1": "#e5e5e5", 			  // AppClient BG
            "--client-bg2": "#ffffff", 			  // AppClient Header-BG
            "--forms": "#ededed", 				  // for searchbar
            "--bg1": "#e3e3e3", 				  // background level 1, f.e. Main-BG
            "--bg2": "#f5f5f5", 				  // background level 2, f.e. Header-BG
            "--bg3": "#ffffff", 				  // background level 3, f.e. Panel-BG
            "--c1": "#000000", 					  // main text color
            "--c2": "#404040", 					  // darker text color, f.e. for less important text
            "--button-bg": "#cccccc", 			  // used only for buttons
            "--red": "#ef4d64", 				  // used f.e. for missed-calls-Icon, end-call-Icon or delete-Buttons
            "--green": "#7cb270", 				  // used f.e. for call-icon or confirm-buttons
            "--yellow": "#17baae", 				  // used for special highlighting
            "--white": "#ffffff",
            "--placeholder-bg": "#afafaf",
            "--placeholder-c": "#ffffff",
            "--badge-bg": "#ef4d64",
            "--badge-c": "#ffffff",
            "--transparent-bg1": "rgba(0,0,0,0.4)",
            "--transparent-bg2": "rgba(0,0,0,0.4)",
            "--logo-c0": "#4a4a4a",               // text
            "--logo-c1": "#808080",               // neutral color (--c2 from light scheme)
            "--logo-c2": "#17baae",               // green (--yellow from light scheme)
            "--logo-c3": "#f59b10",               // orange (--yellow from dark scheme)
            "--watermark-c": "#dbdbdb",
            "--radius": "16px"
        }
    };

function language() {
    return (localStorage.getItem(STORAGE_ID_LANG) || navigator.language || "en").split("-")[0].toLowerCase();
}

function redirect(config, doConnectionTest, onerror, onversionmismatch) {
    var url = "";
    var components = config.items.server.split(/[\?#]+/);
    var hostMod = components[0];
    var args = components.splice(1).join("&");
    if (hostMod.indexOf("/") == -1) hostMod += "/PBX0";

    if (config.items.server && config.items.proxy) {
        url = config.items.proxy + hostMod + "/APPCLIENT/appclient.htm" + (args ? "#" + args : "");
        var xhr = new XMLHttpRequest();
        xhr.timeout = 5000;
        xhr.open('GET', url);
        xhr.onload = function () {
            if (xhr.status === 200) {
                if (xhr.responseURL) url = xhr.responseURL + (args ? "#" + args : "");
                if (doConnectionTest) {
                    var ws = new WebSocket(url.replace("http:", "ws:").replace("https:", "wss:").replace("/appclient.htm", "/websocket").split("#")[0].split("?")[0]);
                    ws.onopen = function () {
                        ws.send(JSON.stringify({ "mt": "CheckBuild" }));
                    };
                    ws.onmessage = function (ev) {
                        var obj = JSON.parse(ev.data);
                        if (obj.mt == "CheckBuildResult") {
                            if (!config.items.launcherVersion
                             || obj.version == config.items.launcherVersion
                             || (config.items.launcherVersion != "13r1" && config.items.launcherVersion != "13r2" && config.items.launcherVersion != "13r3" && config.items.launcherVersion != "14r1"
                              && obj.version && obj.version != "13r1" && obj.version != "13r2" && obj.version != "13r3" && obj.version != "14r1")) {
                                ws.onopen = undefined;
                                ws.onerror = undefined;
                                ws.onclose = undefined;
                                ws.onmessage = undefined;
                                ws.close();
                                config.save();
                                window.location.href = url;
                                return;
                            }
                            else {
                                ws.onopen = undefined;
                                ws.onerror = undefined;
                                ws.onclose = undefined;
                                ws.onmessage = undefined;
                                ws.close();
                                onversionmismatch(obj.version || "");
                            }
                        }
                        else {
                            ws.onopen = undefined;
                            ws.onerror = undefined;
                            ws.onclose = undefined;
                            ws.onmessage = undefined;
                            ws.close();
                            onerror();
                        }
                    };
                    ws.onerror = ws.onclose = function () {
                        console.log("Check Server: Websocket connection failed");
                        ws.onopen = undefined;
                        ws.onerror = undefined;
                        ws.onclose = undefined;
                        ws.onmessage = undefined;
                        onerror();
                    };
                }
                else {
                    config.save();
                    window.location.href = url;
                }
            }
            else {
                console.log("Check Server: HTTP request failed. url=" + url + " status=" + xhr.status);
                onerror();
            }
        };
        xhr.onerror = xhr.ontimeout = function () {
            console.log("Check Server: HTTP request failed. url=" + url + " status=" + xhr.status);
            onerror();
        };
        xhr.send();
    }
    else onerror();
}

function Config() {
    var that = this;
    this.items = JSON.parse(localStorage.getItem(STORAGE_ID_CONFIG) || "{}");
    this.save = function () { localStorage.setItem(STORAGE_ID_CONFIG, JSON.stringify(that.items)); }
    this.clear = function () { localStorage.removeItem(STORAGE_ID_CONFIG); }
}

function Ui(config, lang) {
    var that = this,
        header = new innovaphone.ui1.Node("header", "flex: 0 0 auto; height: 86px; background-color: var(--client-bg2); flex-direction: column; justify-content: center; align-items: center;", null, "screen-header"),
        logo = new innovaphone.ui1.Svg("height: 65px;", "appclient_logo.svg#logo0"),
        main = new innovaphone.ui1.Node("main", "position: relative; flex: 1 1 auto; background-color: var(--bg2); -webkit-overflow-scrolling: touch; -moz-overflow-scrolling: touch; overflow-scrolling: touch; overflow: auto;"),
        // server selection
        form = new innovaphone.ui1.Node("form", "display:flex; flex-direction: column; position:absolute; top: 32px; left: 32px; right: 32px; bottom: 32px; align-items: center;", null, "screen-form"),
        h1 = new innovaphone.ui1.Node("h1").addTranslation(lang, "welcome"),
        text = new innovaphone.ui1.Node("div", "width: 600px; max-width: 100%; margin: 0px 20px 20px 20px; flex: 0 0 auto; font-family: 'titillium'; font-size: 16px; color: var(--c1); text-align: center;").addTranslation(lang, "enterCert"),
        server = new innovaphone.ui1.Node("input", "box-sizing: border-box; display: block; font-family: 'titillium'; font-size: 16px; background-color: var(--forms); color: var(--c1); border: none; box-shadow: none; width: 250px; max-width: 100%; padding: 5px 15px; margin: 20px 20px 35px 20px; flex: 0 0 auto;").addTranslation(lang, "server", "placeholder"),
        submit = new innovaphone.ui1.Node("input", "width: 250px; max-width: 100%; margin: 0px 20px 20px 20px; flex: 0 0 auto;").addTranslation(lang, "conf", "value"),
        submit_platform = new innovaphone.ui1.Node("input", "width: 250px; max-width: 100%; margin: 0px 20px 20px 20px; flex: 0 0 auto;").addTranslation(lang, "platsetup", "value"),
        help = new innovaphone.ui1.Node("div", "font-family: 'titillium'; color: var(--c2); font-size: 16px; text-align: center; max-width: 100%; flex: 0 0 auto; margin: 20px 0px 0px;").addTranslation(lang, "help"),
        connecting = new innovaphone.ui1.Node("div", "display: none; max-width: 100%; flex: 0 0 auto; font-family: 'titillium'; font-size: 16px; color: var(--yellow); text-align: center; margin: 0px 20px 20px 20px;").addTranslation(lang, "connecting"),
        error = new innovaphone.ui1.Node("div", "display: none; width: 550px; max-width: 100%; margin: 0px 20px 20px 20px; flex: 0 0 auto; color: var(--yellow); text-align: center; font-size: 16px;").addTranslation(lang, "serverUnreachable"),
        // version mismatch
        versionMismatch = new innovaphone.ui1.Node("div", "display:flex; flex-direction: column; position:absolute; top: 32px; left: 32px; right: 32px; bottom: 32px; align-items: center;", null, "screen-form"),
        versionMismatchTitle = new innovaphone.ui1.Node("div", "flex: 0 0 auto; color: var(--c1); font-size: 16px; margin: 15px; max-width: 400px; text-align: center;"),
        version = versionMismatchTitle.createTranslation(lang, "loginVersionMismatchTitle", null, [config.items.launcherVersion]),
        versionMismatchText = new innovaphone.ui1.Node("div", "flex: 0 0 auto; color: var(--c1); font-size: 16px; margin: 15px; max-width: 400px; text-align: center;").addTranslation(lang, "loginVersionMismatchText"),
        versionMismatchContinueButton = new innovaphone.ui1.Node("a", "font-family: 'titillium',sans-serif; text-decoration: underline; font-size: 16px; color: var(--c2); max-width: 100%; margin: 25px 5px 5px 5px; flex: 0 0 auto;").addTranslation(lang, "clientContinue").testId("VersionMismatchContinue"),
        versionMismatchAbortButton = new innovaphone.ui1.Node("a", "font-family: 'titillium',sans-serif; text-decoration: underline; font-size: 16px; color: var(--c2); max-width: 100%; margin: 5px; flex: 0 0 auto;").addTranslation(lang, "loginSwitchServer"),
        configIframe = new innovaphone.ui1.Node("iframe", "width: 100%; height: 100%; border: none; margin: 0; padding: 0; position: relative; z-index: 9999;");

    this.createNode("body", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; display: flex; flex-direction: column; margin: 0px; padding: 0px; background-color: var(--bg2)");
    form.container.setAttribute("action", "javascript:");
    server.container.setAttribute("id", "server-login");
    if (innovaphone.ui1.lib.browser.simulator) server.container.setAttribute("aria-label", "server-login");
    server.container.setAttribute("type", "url");
    server.container.setAttribute("novalidate", "novalidate")
    server.container.value = config.items.server || "";
    submit.container.setAttribute("id", "server-submit");
    if (innovaphone.ui1.lib.browser.simulator) submit.container.setAttribute("aria-label", "server-submit");
    submit.container.setAttribute("type", "submit");
    submit.container.setAttribute("formnovalidate", "formnovalidate");
    submit.container.addEventListener("click", function () {
        config.items.server = server.container.value.trim();
        error.container.style.display = "none";
        connecting.container.style.display = "block";

        redirect(config, true, function () {
            connecting.container.style.display = "none";
            error.container.style.display = "block";
        }, function (pbxVersion) {
            version.setArgs([pbxVersion]);
            versionMismatchTitle.container.style.display = pbxVersion ? "block" : "none";
            connecting.container.style.display = "none";
            form.container.style.display = "none";
            versionMismatch.container.style.display = "flex";
        });
    });

    submit_platform.container.setAttribute("id", "platform-submit");
    if (innovaphone.ui1.lib.browser.simulator) submit_platform.container.setAttribute("aria-label", "platform-submit");
    submit_platform.container.setAttribute("type", "submit");
    submit_platform.container.setAttribute("formnovalidate", "formnovalidate");
    submit_platform.container.addEventListener("click", function () {
        pwd = config.items.servicePwd;

        configIframe.setAttribute("src", "http://127.0.0.1:8080/linuxsetup/setup.htm?servicePwd=" + pwd);
        window.addEventListener(
            "message",
            (event) => {
                if (event.origin !== "http://127.0.0.1:8080") return;
                if (event.data === "closeIFrame") {
                    main.rem(configIframe);
                }
            },
            false,
        );
        main.add(configIframe);
    });
    // version mismatch
    versionMismatch.container.style.display = "none";
    versionMismatchAbortButton.container.addEventListener("click", function () {
        connecting.container.style.display = "none";
        form.container.style.display = "flex";
        versionMismatch.container.style.display = "none";
    });
    versionMismatchContinueButton.container.addEventListener("click", function () {
        redirect(config);
    });
    header.add(logo);
    form.add(h1);
    form.add(text);
    form.add(server);
    form.add(submit);
    if (config.items.platform == "linux" || (navigator.userAgent.indexOf("IP270") != -1)) form.add(submit_platform);
    form.add(connecting);
    form.add(error);
    form.add(help);
    versionMismatch.add(versionMismatchTitle);
    versionMismatch.add(versionMismatchText);
    versionMismatch.add(versionMismatchContinueButton);
    versionMismatch.add(versionMismatchAbortButton);
    main.add(form);
    main.add(versionMismatch);
    this.add(header);
    this.add(main);
    server.container.focus();
}
Ui.prototype = innovaphone.ui1.nodePrototype;

function NotSupportedPage() {
    var warning = new innovaphone.ui1.Div("text-align: center; font-size: 24px; font-family: titillium; color: #414141;", "The version of the web browser control is not supported. Update if possible.");
    this.createNode("body", "background-color: #dde2e3; padding: 40px;");
    this.add(warning);
}
NotSupportedPage.prototype = innovaphone.ui1.nodePrototype;

function start() {
    if (!browserSupported()) {
        new NotSupportedPage();
        return;
    }

    var config = new Config(),
        parameters = {};

    (location.hash.split("#")[1] || "").split("&").concat((location.search.split("?")[1] || "").split("&")).forEach(function (p) {
        if (p) {
            var item = p.split("=");
            parameters[item[0]] = decodeURIComponent(item[1] || "");
        }
    });

    if (parameters.action == "config") {
        config.items.current = undefined;
        config.items.primary = undefined;
        config.items.secondary = undefined;
    }
    config.items.platform = parameters.platform;
    config.items.originalUrl = undefined;
    config.items.redirected = undefined;

    for (var key in parameters) {
        if (key != "action" && parameters[key]) config.items[key] = parameters[key];
    }
    config.items.start = window.location.href.split("?")[0];

    if (config.items.server && parameters.action != "config") {
        redirect(config, false, function () { showUi(config); });
    }
    else showUi(config);
}

function showUi(config) {
    var lang = new innovaphone.lib1.Languages(innovaphone.pbx.appclient.start.lang, language()),
        schemes = new innovaphone.ui1.CssVariables(startSchemes),
        ui = new Ui(config, lang);

    var systemSchemeSupported = window.matchMedia && window.matchMedia("(prefers-color-scheme:light)").matches != window.matchMedia("prefers-color-scheme:dark").matches && window.navigator.userAgent.indexOf("IP270") == -1;
    var clientScheme = localStorage.getItem(STORAGE_ID_SCHEME);
    var systemScheme = null;
    if (systemSchemeSupported) systemScheme = window.matchMedia("(prefers-color-scheme:light)").matches ? "light" : "dark";
    schemes.activate(clientScheme || systemScheme || "dark");    
}

function browserSupported() {
    try {
        if (!innovaphone.ui1.cssVariablesSupported()) return false;
        if (!localStorage) return false;
        localStorage.setItem("localStorageTest", "test");
        localStorage.removeItem("localStorageTest");
    }
    catch (e) {
        return false;
    }
    return true;
}
