var innovaphone = innovaphone || {};
innovaphone.pbx = innovaphone.pbx || {};
innovaphone.pbx.appclient = innovaphone.pbx.appclient || {};
innovaphone.pbx.appclient.ProvisioningPage = innovaphone.pbx.appclient.ProvisioningPage || function (start) {

    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"
            }
        };

    var connection;
    var provisionLocation;

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

    function redirectPBX(config, doConnectionTest, onerror, onversionmismatch) {
        if (config.items.server && config.items.proxy) {
            var url = "";
            var components = config.items.server.split(/[\?#]+/);
            var hostMod = components[0];
            var args = components.splice(1).join("&");
            if (hostMod.indexOf("/") == -1) hostMod += "/PBX0";
            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;
                    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-size: 16px; color: var(--c1); text-align: center;").addTranslation(lang, "enterProv"),
            provisioningCode = new innovaphone.ui1.Node("input", "box-sizing: border-box; display: block; 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; -webkit-appearance: none;").addTranslation(lang, "provCode", "placeholder"),
            submit = new innovaphone.ui1.Node("input", "width: 250px; max-width: 100%; margin: 0px 20px 20px 20px; flex: 0 0 auto;").addTranslation(lang, "startProv", "value"),
            skip_provisioning = new innovaphone.ui1.Node("input", "width: 250px; max-width: 100%; margin: 0px 20px 20px 20px; flex: 0 0 auto;").addTranslation(lang, "skipProv", "value"),
            help = new innovaphone.ui1.Node("div", "color: var(--c2); font-size: 16px; text-align: center; max-width: 100%; flex: 0 0 auto; margin: 20px 0px 0px;").addTranslation(lang, "provHelp"),
            connecting = new innovaphone.ui1.Node("div", "display: none; max-width: 100%; flex: 0 0 auto; 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", "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", "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:");
        provisioningCode.container.setAttribute("id", "provisioning-code");
        if (innovaphone.ui1.lib.browser.simulator) provisioningCode.container.setAttribute("aria-label", "provisioning-code");
        provisioningCode.container.setAttribute("type", "number");
        provisioningCode.container.setAttribute("novalidate", "novalidate")
        provisioningCode.container.value = "";
        submit.container.setAttribute("id", "provisioning-code-submit");
        if (innovaphone.ui1.lib.browser.simulator) submit.container.setAttribute("aria-label", "provisioning-code-submit");
        submit.container.setAttribute("type", "submit");
        submit.container.setAttribute("formnovalidate", "formnovalidate");
        submit.container.addEventListener("click", function () {
            config.items.provisioningCode = provisioningCode.container.value.trim();
            error.container.style.display = "none";
            connecting.container.style.display = "block";

            connection.send({ mt: "provisioning", code: config.items.provisioningCode });
        });

        skip_provisioning.container.setAttribute("id", "skip-provisioning");
        if (innovaphone.ui1.lib.browser.simulator) skip_provisioning.container.setAttribute("aria-label", "skip-provisioning");
        skip_provisioning.container.setAttribute("type", "submit");
        skip_provisioning.container.setAttribute("formnovalidate", "formnovalidate");
        skip_provisioning.container.addEventListener("click", function () {
            config.items.skipProvisioning = true;
            config.save();
            let href = provisionLocation.href.replace("provision.htm", "start.htm");
            window.location.href = href;
        });
        // 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 () {
            redirectPBX(config);
        });
        header.add(logo);
        form.add(h1);
        form.add(text);
        form.add(provisioningCode);
        form.add(submit);
        form.add(skip_provisioning);
        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);
        provisioningCode.container.focus();
    }
    Ui.prototype = innovaphone.ui1.nodePrototype;

    function NotSupportedPage() {
        var warning = new innovaphone.ui1.Div("text-align: center; font-size: 24px; 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( config, parameters) {
        if (!browserSupported()) {
            new NotSupportedPage();
            return;
        }

        if (config.items.provisioningCode && parameters.action != "config") {
            redirectPBX(config, false, function () { showUi(config); });
        } else if (config.items.skipProvisioning && parameters.action != "config") {
            let href = provisionLocation.href.replace("provision.htm", "start.htm");
            window.location.href = href;
        }
        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;
    }

    function App(start) {
        var that = this;
        console.log("Start Provisioning");

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

        console.log("Current provisionLocation: " + provisionLocation);

        if (typeof provisionLocation == 'undefined') {
            provisionLocation = window.location;
            console.log("Set provisionLocation to: " + provisionLocation);
        }

        (location.search.substring(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];

        start(config, parameters);

        pwd = config.items.servicePwd;
        connection = new innovaphone.appwebsocket.Connection(start.url, "@ip270", pwd);


        connection.onconnected = function (domain, user, dn) {
            //connection.send({ mt: "MonitorStatusChanges", value: "1" })
            //connection.send({ mt: "provisioning", code: "012 345 678 901" });
        };
        connection.onmessage = function (msg) {
            if (msg.mt == "provisioningResponse") {
                config.items.server = msg.gk1;
                redirectPBX(config, true, function () {
                    console.err("Error connecting to " + msg.gk1);
                }, 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";
                });
            }
        };
        connection.onclosed = function () { console.log("**** CLOSE IP270"); };

    }

    return new App(start);
}
