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

    var schemeDefinitions = {
        "dark": {
            "--client-bg2": "#161616", 			  // AppClient Header-BG
            "--main-bg": "#282828",
            "--tabs-bg": "#333333",
            "--hotkey-bg": "#414141",
            "--content-bg": "#474747",
            "--icon-bg": "#ffffff",
            "--c1": "#efefef",
            "--c2": "#939393",
            "--check-bg": "#1aa0ad",
            "--check-c": "#ffffff",
            "--uncheck-bg": "#ffffff",
            "--button": "#3a3a3a",
            "--button-hover": "#303030",
            "--radio-border": "#efefef",
            "--highlight-bg": "#595959", // used as highlight-color, f.e. for Hover (but not for hover over buttons)
            "--button-bg": "#3D3D3D", // used only for buttons
            "--accent": "#F59b10", // AppIcon-Color, please change this value to your App-Icon-Color
            "--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
            "--search-bg": "#1E1E1E",
            "--line2px": "#3A3A3A"
        },
        "light": {
            "--client-bg2": "#ffffff",
            "--main-bg": "#cccccc",
            "--tabs-bg": "#ffffff",
            "--hotkey-bg": "#ffffff",
            "--content-bg": "#f1f1f1",
            "--icon-bg": "#000000",
            "--c1": "#000000",
            "--c2": "#404040",
            "--check-bg": "#1aa0ad",
            "--check-c": "#ffffff",
            "--uncheck-bg": "#9fdad6",
            "--button": "#cccccc",
            "--button-hover": "#e0e0e0",
            "--radio-border": "#0f0f0f",
            "--highlight-bg": "#f0f0f0",
            "--button-bg": "#ffffff",
            "--accent": "#F4B637",
            "--red": "#ef4d64",
            "--green": "#7cb270",
            "--yellow": "#17baae",
            "--search-bg": "#ededed",
            "--line2px": "#E2E2E2"
        }
    };

    var icons = {
        trace: { viewbox: '0 0 20 20', code: '<path d="M16.32,14.17a9.19,9.19,0,0,0,1.53-5.09A9,9,0,0,0,8.92,0,9,9,0,0,0,0,9.08a9,9,0,0,0,8.92,9.09,8.78,8.78,0,0,0,5.52-2L18.06,20,20,18Zm-7.4,1.2A6.24,6.24,0,0,1,2.75,9.08,6.24,6.24,0,0,1,8.92,2.8,6.24,6.24,0,0,1,15.1,9.08,6.24,6.24,0,0,1,8.92,15.37ZM9.8,9.8H8.17V4.9H9.8Zm0,3.27H8.17V11.44H9.8Z"></path>' },
        externalapps: { viewbox: '0 0 20 20', code: '<path d="M17.51,6.66l-3.08,3.89a4.7,4.7,0,0,0-.62-2.44l2.13-2.69a1.83,1.83,0,0,0-.3-2.56,1.84,1.84,0,0,0-2.57.3L8.93,8.4a1.88,1.88,0,0,0-.29.54,2,2,0,0,0-.09.8A1.79,1.79,0,0,0,9.24,11a1.67,1.67,0,0,0,.78.35L8.71,13A3.49,3.49,0,0,1,8,12.53a3.8,3.8,0,0,1-1.31-2A3.5,3.5,0,0,1,6.57,10a3.75,3.75,0,0,1,0-.67c0-.09,0-.18,0-.28a2.25,2.25,0,0,1,.06-.36c0-.11.06-.23.1-.34l.09-.24a4,4,0,0,1,.52-.92L11.5,1.92a3.83,3.83,0,0,1,6,4.74ZM13.43,10.2a1.53,1.53,0,0,0,0-.3c0-.13-.05-.26-.08-.38s-.05-.2-.08-.3L13.14,9h0l-.06-.12A2.06,2.06,0,0,0,13,8.59,3.12,3.12,0,0,0,12.57,8h0A2.75,2.75,0,0,0,12,7.47,3.49,3.49,0,0,0,11.29,7L10,8.68a1.8,1.8,0,0,1,.78.36,1.71,1.71,0,0,1,.51.63,2,2,0,0,1,.15.47v0a2.68,2.68,0,0,1,0,.49v0a1.83,1.83,0,0,1-.09.39h0a1.42,1.42,0,0,1-.08.18,1.82,1.82,0,0,1-.2.36h0L6.93,16.84a1.84,1.84,0,0,1-1.22.68H5.39l-.31-.05h0a1.82,1.82,0,0,1-1-2.91l2.11-2.66a5,5,0,0,1-.6-1.82c0-.21,0-.43,0-.64L2.49,13.33a3.85,3.85,0,0,0,.63,5.38h0a3.94,3.94,0,0,0,1.41.69l.14,0a3.75,3.75,0,0,0,.82.1h0a3.39,3.39,0,0,0,.45,0A3.83,3.83,0,0,0,8.5,18.08l4.14-5.24a3.94,3.94,0,0,0,.39-.61l.09-.22c.06-.15.12-.29.17-.44a2.61,2.61,0,0,0,.06-.27,2.93,2.93,0,0,0,.07-.41,2.29,2.29,0,0,0,0-.25s0,0,0-.06A2.38,2.38,0,0,0,13.43,10.2Z"></path>' },
        add: { viewbox: '0 0 20 20', code: '<path d="M8.24,8.24V0h3.52V8.24H20v3.52H11.76V20H8.24V11.76H0V8.24Z"></path>' },
        settings: { viewbox: '0 0 24 24', code: '<path d="M20.5,11.5c0-1.3,0.9-2.5,2.1-2.9C22.9,8.5,23,8.2,22.9,8c-0.2-0.7-0.5-1.3-0.8-2c-0.2-0.3-0.6-0.4-0.8-0.1 c-0.7,0.6-1.7,0.8-2.7,0.5c-0.9-0.3-1.7-1-2-2c-0.3-1-0.1-2,0.5-2.7C17.3,1.4,17.3,1,17,0.8c-0.6-0.3-1.3-0.6-2-0.8 c-0.3-0.1-0.6,0.1-0.7,0.3c-0.4,1.2-1.5,2.1-2.9,2.1S9,1.6,8.6,0.4C8.5,0.1,8.2-0.1,8,0C7.3,0.2,6.6,0.5,6,0.8 C5.7,1,5.6,1.4,5.8,1.7c0.6,0.7,0.8,1.7,0.5,2.7c-0.3,0.9-1,1.7-2,2c-1,0.3-2,0.1-2.7-0.5C1.4,5.6,1,5.7,0.8,6C0.5,6.6,0.2,7.3,0,8 c-0.1,0.3,0.1,0.6,0.3,0.7c1.2,0.4,2.1,1.5,2.1,2.9S1.6,14,0.4,14.3C0.1,14.4-0.1,14.7,0,15c0.2,0.7,0.5,1.3,0.8,2 c0.2,0.3,0.6,0.4,0.8,0.1c0.7-0.6,1.7-0.8,2.7-0.5c0.9,0.3,1.7,1,2,2c0.3,1,0.1,2-0.5,2.7C5.6,21.6,5.7,22,6,22.1 c0.6,0.3,1.3,0.6,2,0.8c0.3,0.1,0.6-0.1,0.7-0.3c0.4-1.2,1.5-2.1,2.9-2.1s2.5,0.9,2.9,2.1c0.1,0.3,0.4,0.4,0.7,0.3 c0.7-0.2,1.3-0.5,2-0.8c0.3-0.2,0.4-0.6,0.1-0.8c-0.6-0.7-0.8-1.7-0.5-2.7c0.3-0.9,1-1.7,2-2c1-0.3,2-0.1,2.7,0.5 c0.3,0.2,0.7,0.2,0.8-0.1c0.3-0.6,0.6-1.3,0.8-2c0.1-0.3-0.1-0.6-0.3-0.7C21.4,14,20.5,12.8,20.5,11.5z M11.4,16.7 c-2.9,0-5.2-2.3-5.2-5.2s2.3-5.2,5.2-5.2s5.2,2.3,5.2,5.2S14.3,16.7,11.4,16.7z"></path>' },
        checkmark: { viewbox: '-2 0 16 10', code: '<path d=\"M4.2,9.6L0,5.4L1.4,4l2.8,2.8L11,0l1.4,1.4L4.2,9.6z\"></path>' },
        download: { viewbox: '0 0 20 20', code: '<path d="M14.33,6.21l2.17,2.2L10,15,3.5,8.41l2.17-2.2L8.56,9.14V0h2.88V9.14ZM16.5,18H3.5v2h13Z"></path>' },
        info: { viewbox: '0 0 20 20', code: '<path d="M12,5H10V3h2ZM10,15.62,11,9V8H9.31L7,8.69v1.39l2.25-.7L8,16v1h2.12L13,14.92v-.69Z"></path>' },
        help: { viewbox: '0 0 20 20', code: '<path d="M8.62.38h2.07A3.3,3.3,0,0,1,14,3.67V5.92A3.78,3.78,0,0,1,12.38,9l-1.16.82a.52.52,0,0,0-.23.43v3.2a.52.52,0,0,1-.52.52H8.53A.52.52,0,0,1,8,13.46v-4a1.93,1.93,0,0,1,.84-1.6l1.39-1A1.81,1.81,0,0,0,11,5.44v-1A1.09,1.09,0,0,0,9.9,3.38H9.09A1.09,1.09,0,0,0,8,4.47v.78a.53.53,0,0,1-.53.53H5.53A.52.52,0,0,1,5,5.26V4A3.61,3.61,0,0,1,8.62.38ZM8.39,20h2.22a.4.4,0,0,0,.39-.39V17.39a.4.4,0,0,0-.39-.39H8.39a.4.4,0,0,0-.39.39v2.22A.4.4,0,0,0,8.39,20Z"></path>' },
        close: { viewbox: '0 0 20 20', code: '<path d="M7.5,10,1.68,4.18l2.5-2.5L10,7.5l5.82-5.82,2.5,2.5L12.5,10l5.82,5.82-2.5,2.5L10,12.5,4.18,18.32l-2.5-2.5Z"></path>' },
        offline: { viewbox: '-3 -3 16 16', code: '<path d="M10,5A5,5,0,1,1,5,0,5,5,0,0,1,10,5Z"></path>' },
        edit: { viewbox: '0 0 20 20', code: '<path d="M19.67,4.82,16.38,8.19,11.1,3.75,14.4.38A1,1,0,0,1,15.66.15l4.13,3.48A.81.81,0,0,1,19.67,4.82ZM.86,14.25,0,19.3A.54.54,0,0,0,.8,20l5.34-1.26,8.64-8.86L9.51,5.39Z"></path>' },
        del: { viewbox: '0 0 20 20', code: '<path d="M8.17,18h-2V8h2Zm6,0h-2V8h2ZM3.17,6V19c0,.89,1,1,1,1h12c1,0,1-.37,1-1V6Zm0-1h14a1,1,0,0,0,1-1,1,1,0,0,0-1-1h-5V1c.05-.22-.59-1-.89-1H9.06c-.28,0-.89.72-.89,1V3h-5a.9.9,0,0,0-1,1A1,1,0,0,0,3.17,5Z"></path>' },
        check: { viewbox: '0 0 20 20', code: '<path d=\"M6.67,17.26.81,11.38a1.14,1.14,0,0,1,0-1.62h0a1.15,1.15,0,0,1,1.63,0L6.67,14,17.56,3.08a1.15,1.15,0,0,1,1.63,0h0a1.14,1.14,0,0,1,0,1.62Z\"></path>' },
        mail: { viewbox: '0 0 20 20', code: '<path d=\"M20,5.34a.43.43,0,0,0,0,0V16.86a.68.68,0,0,1-.69.64H.69A.71.71,0,0,1,0,16.75V5.39s0,0,0-.07L9.6,14.05a.72.72,0,0,0,.4.24c.2,0,.3,0,.4-.12ZM20,2.5H0l9.52,9a.75.75,0,0,0,1,0Z\"></path>' },
        speaker: { viewbox: '0 0 20 20', code: '<path d="M1.8,12.25H.9a.9.9,0,0,1-.9-.9V8.64a.9.9,0,0,1,.9-.9H5.21A24.54,24.54,0,0,0,10,3.59a.45.45,0,0,1,.64,0,.52.52,0,0,1,.14.32V16.09a.46.46,0,0,1-.45.46.46.46,0,0,1-.32-.13l-.35-.36a25.58,25.58,0,0,0-4.5-3.81H4.51M15,12.91a12.19,12.19,0,0,0,0-5.82,1,1,0,1,0-1.94.49,10.16,10.16,0,0,1,0,4.84,1,1,0,0,0,.72,1.22l.25,0A1,1,0,0,0,15,12.91Zm3.83,1.33.33-1.33a11.94,11.94,0,0,0,0-5.82l-.33-1.33A1,1,0,0,0,17.65,5a1,1,0,0,0-.73,1.21l.33,1.33a10,10,0,0,1,0,4.85l-.33,1.34A1,1,0,0,0,17.65,15l.24,0A1,1,0,0,0,18.86,14.24Z"></path>' },
        hotkey: { viewbox: '0 0 20 20', code: '<path d="m6,2c-2.21,0-4,1.79-4,4v8c0,2.21,1.79,4,4,4h8c2.21,0,4-1.79,4-4V6c0-2.21-1.79-4-4-4H6m0-2h8c3.31,0,6,2.69,6,6v8c0,3.31-2.69,6-6,6H6c-3.31,0-6-2.69-6-6V6C0,2.69,2.69,0,6,0Zm7.5,15h-7c-.55,0-1-.45-1-1s.45-1,1-1h7c.55,0,1,.45,1,1s-.45,1-1,1Z"></path>' },
        handset: { viewbox: '0 0 20 20', code: '<path d="M8.68,1.07a.36.36,0,0,1,.18.38c-.17.85-.33,4.08-.44,4.18-.34.28-2.44.81-2.88,1.31-.31.35,1,5.69,1,5.69a5.67,5.67,0,0,0,2.59,1,.44.44,0,0,1,.35.42c.05,1,.22,4,.18,4.87a.57.57,0,0,1-.44.5c-.64.16-1.84.46-2.33.56a.4.4,0,0,1-.47-.26C5.7,17.58,3.6,6.94,3.62,6.5A28.41,28.41,0,0,1,5.42.2.36.36,0,0,1,5.83,0,14.35,14.35,0,0,1,8.68,1.07ZM11.19,8.7,11,8.59a1,1,0,0,1-.28-1.39,10,10,0,0,0,1.64-4.57,1,1,0,0,1,2,.2,12.12,12.12,0,0,1-2,5.48A1,1,0,0,1,11.19,8.7Zm3.16,2.54a.65.65,0,0,1-.22-.11,1,1,0,0,1-.28-1.38l.76-1.15A10,10,0,0,0,16.25,4l.13-1.37a1,1,0,0,1,1.1-.9,1,1,0,0,1,.89,1.1l-.13,1.36a12.07,12.07,0,0,1-2,5.48l-.76,1.14A1,1,0,0,1,14.35,11.24Z"></path>' },
        headphone: { viewbox: '0 0 20 20', code: '<path d="M8.25,15.25c0,1.48-1.57,1.68-3,1.71l-1-9.26.41-.26c1-.42,2.59.33,2.59,1.43ZM9.51,0A9.52,9.52,0,0,0,.21,9.49l.32,1.06c0,.21,0,.42,0,.64L2,13.52a5.55,5.55,0,0,0,1.19,2.21,5.11,5.11,0,0,0,1.35,1l-1-8.66A2.13,2.13,0,0,0,2.79,8,2.45,2.45,0,0,0,2.4,8,7.46,7.46,0,0,1,9.55,1.94,7.47,7.47,0,0,1,16.71,8a2.58,2.58,0,0,0-.39,0c-.11,0-.2,0-.31,0L15,16.4l-2.91,2.32a1,1,0,0,0-.79-.42H9a1,1,0,0,0-1,1H8a1.17,1.17,0,0,0,1.17,1.17h2a1.17,1.17,0,0,0,.76-.3l0,0,5-4L18,12.65l.55-1.46c0-.34,0-.67,0-1h0l.3-.73A9.59,9.59,0,0,0,9.51,0Zm5,7.42A1.79,1.79,0,0,0,12.16,9l-1,6.37c0,1.57,1.44,1.52,3,1.52l.14,0,1-9-.07,0h0Z"></path>' },
        ring: { viewbox: '0 0 20 20', code: '<path d="M17,15.25v.5A1.22,1.22,0,0,1,15.83,17H11.34v1.61A1.35,1.35,0,0,1,10,20H9.81A1.35,1.35,0,0,1,8.5,18.61V17H4a1.22,1.22,0,0,1-1.19-1.25v-.5A1.22,1.22,0,0,1,4,14h.9a.77.77,0,0,0,.75-.79V6.87A1.82,1.82,0,0,1,7.44,5H8.5V3.5A1.46,1.46,0,0,1,9.92,2h0a1.46,1.46,0,0,1,1.42,1.5V5H12.4a1.82,1.82,0,0,1,1.77,1.88v6.33a.77.77,0,0,0,.75.79h.91A1.22,1.22,0,0,1,17,15.25ZM20,6c0-4.75-3.19-6-4.88-6a1,1,0,0,0-.95,1,1,1,0,0,0,.95,1c.12,0,3,0,3,4A.95.95,0,1,0,20,6ZM1.89,6c0-3.83,2.69-4,3-4a1,1,0,0,0,.94-1,1,1,0,0,0-1-1C3.19,0,0,1.25,0,6A1,1,0,0,0,.94,7,1,1,0,0,0,1.89,6Z"></path>' },
        backlight: {
            viewbox: '0 0 32 32',
            code: '<path d="m 15.5,23.5 c 3.875,0 7,-3.15 7,-7 0,-3.85 -3.15,-7.0000003 -7,-7.0000003 -3.85,0 -7,3.1500003 -7,7.0000003 0,3.85 3.125,7 7,7 z"/><path d="m 16.525,6.2499997 v -3.225 c 0,-0.575 -0.45,-1.025 -1.025,-1.025 -0.575,0 -1.025,0.45 -1.025,1.025 v 3.225 c 0,0.575 0.45,1.025 1.025,1.025 0.575,0 1.025,-0.45 1.025,-1.025 z"/><path d="m 14.475,26.75 v 3.225 c 0,0.575 0.45,1.025 1.025,1.025 0.575,0 1.025,-0.45 1.025,-1.025 V 26.75 c 0,-0.575 -0.45,-1.025 -1.025,-1.025 -0.575,0 -1.025,0.45 -1.025,1.025 z"/><path d="m 23.475,9.9749997 2.275,-2.275 c 0.4,-0.4 0.4,-1.05 0,-1.45 -0.4,-0.4 -1.05,-0.4 -1.45,0 l -2.275,2.275 c -0.4,0.4 -0.4,1.05 0,1.45 0.2,0.2000003 0.45,0.3000003 0.725,0.3000003 0.275,0 0.525,-0.1 0.725,-0.3000003 z"/><path d="m 5.25,26.75 c 0.2,0.2 0.45,0.3 0.725,0.3 0.25,0 0.525,-0.1 0.725,-0.3 l 2.275,-2.275 c 0.4,-0.4 0.4,-1.05 0,-1.45 -0.4,-0.4 -1.05,-0.4 -1.45,0 L 5.25,25.3 c -0.4,0.4 -0.4,1.05 0,1.45 z"/><path d="m 30,16.5 c 0,-0.575 -0.45,-1.025 -1.025,-1.025 H 25.75 c -0.575,0 -1.025,0.45 -1.025,1.025 0,0.575 0.45,1.025 1.025,1.025 h 3.225 c 0.55,0 1.025,-0.45 1.025,-1.025 z"/><path d="M 2.025,17.525 H 5.25 c 0.575,0 1.025,-0.45 1.025,-1.025 0,-0.575 -0.45,-1.025 -1.025,-1.025 H 2.025 C 1.45,15.475 1,15.925 1,16.5 c 0,0.575 0.475,1.025 1.025,1.025 z"/><path d="m 25.025,27.05 c 0.25,0 0.525,-0.1 0.725,-0.3 0.4,-0.4 0.4,-1.05 0,-1.45 l -2.275,-2.275 c -0.4,-0.4 -1.05,-0.4 -1.45,0 -0.4,0.4 -0.4,1.05 0,1.45 L 24.3,26.75 c 0.2,0.2 0.475,0.3 0.725,0.3 z"/><path d="m 8.975,9.9749997 c 0.4,-0.4 0.4,-1.05 0,-1.45 l -2.275,-2.275 c -0.4,-0.4 -1.05,-0.4 -1.45,0 -0.4,0.4 -0.4,1.05 0,1.45 l 2.275,2.275 C 7.725,10.175 7.975,10.275 8.25,10.275 c 0.275,0 0.525,-0.1 0.725,-0.3000003 z"/>'
        }
    };

    const checkBoxStyle = "flex: 0 0 auto; width: 18px; height: 18px; margin: 7px; border-radius: 12.5%; background-color: var(--uncheck-bg); fill: var(--uncheck-bg); cursor: pointer";

    function AutostartFlag(owner, lang) {
        var that = this,
            force = false,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 auto; color: var(--c1); font-size: 14px; line-height: 20px; margin: 0 8px 0 4px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "autostartText"),
            active = 0;

        this.createNode("button", "flex: 1 1 150px; margin: 0 8px 0 4px; padding: 0; text-align: left; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; border-radius: 5px; overflow: hidden;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            if (force === false) {
                active = !active;
                owner.activateAutostartFlag(active);
                checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
                checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            }
        });
        this.initAutostart = function (initActive, forceAu) {
            active = initActive;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            this.setDisabled(forceAu);
            this.container.style.opacity = forceAu ? "0.5" : null;
            force = forceAu;
        };
    };
    AutostartFlag.prototype = innovaphone.ui1.nodePrototype;

    function NotificationsFlag(owner, lang) {
        var that = this,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 auto; color: var(--c1); font-size: 14px; line-height: 20px; margin: 0 8px 0 4px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "desktopNotificationsText"),
            active = false,
            force = false;

        this.createNode("button", "flex: 1 1 150px; margin: 0 8px 0 4px; padding: 0; text-align: left; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; border-radius: 5px; overflow: hidden;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            if (force == false) {
                active = !active;
                owner.activateShowDesktopNotificationsFlag(active);
                checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
                checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            }
        });
        this.initNotifications = function (initActive, forceSn) {
            force = forceSn;
            active = initActive;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            this.setDisabled(force);
            this.container.style.opacity = force ? "0.5" : null;
        };
    };
    NotificationsFlag.prototype = innovaphone.ui1.nodePrototype;

    function NoVpnAddressesFlag(owner, lang) {
        var that = this,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 auto; color: var(--c1); font-size: 14px; line-height: 20px; margin: 0 8px 0 4px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "noVpnAddressesFlagText"),
            active = false,
            force = false;

        this.createNode("button", "flex: 1 1 150px; margin: 0 8px 0 4px; padding: 0; text-align: left; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; border-radius: 5px; overflow: hidden;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            if (force == false) {
                active = !active;
                owner.activateNoVpnAddressesFlag(active);
                checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
                checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            }
        });
        this.initNoVpnAddresses = function (initActive, forceSn) {
            force = forceSn;
            active = initActive;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            this.setDisabled(force);
            this.container.style.opacity = force ? "0.5" : null;
        };
    };
    NoVpnAddressesFlag.prototype = innovaphone.ui1.nodePrototype;

    function RingInHeadsetFlag(owner, lang) {
        var that = this,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); font-size: 14px; margin: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "ringHeadset"),
            active = false,
            force = false;

        this.createNode("div", "flex: 1 1 150px; margin: 5px 5px 5px 10px; display: flex; flex-direction: row; flex-wrap: nowrap; overflow: hidden; order: 1;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            if (force == false) {
                active = !active;
                owner.activateRingInHeadsetFlag(active);
                checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
                checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            }
        });
        this.initRingInHeadset = function (initActive, forceSn) {
            force = forceSn;
            active = initActive;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            this.setDisabled(force);
            this.container.style.opacity = force ? "0.5" : null;
        };
    };
    RingInHeadsetFlag.prototype = innovaphone.ui1.nodePrototype;

    function AvoidNativeCallScreenFlag(owner, lang) {
        var that = this,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); font-size: 14px; margin: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "avoidNativeCallScreen"),
            active = false,
            force = false;

        this.createNode("div", "flex: 1 1 150px; margin: 5px 5px 5px 5px; display: flex; flex-direction: row; flex-wrap: nowrap; overflow: hidden; order: 1;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            if (force == false) {
                active = !active;
                owner.activateAvoidNativeCallScreenFlag(active);
                checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
                checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            }
        });
        this.initAvoidNativeCallScreen = function (initActive, forceSn) {
            force = forceSn;
            active = initActive;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            this.setDisabled(force);
            this.container.style.opacity = force ? "0.5" : null;
        };
        this.getValue = function () { return active; }
    };
    AvoidNativeCallScreenFlag.prototype = innovaphone.ui1.nodePrototype;

    function HideFromNativeCallListFlag(owner, lang) {
        var that = this,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); font-size: 14px; margin: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "hideFromNativeCallList"),
            active = false,
            force = false,
            disabled = false;

        function disable(isDisabled) {
            disabled = isDisabled;
            that.setDisabled(isDisabled);
            that.container.style.opacity = isDisabled ? "0.5" : null;
        }
        function activate(isActive) {
            active = isActive;
            owner.activateHideFromNativeCallListFlag(active);
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
        }

        this.createNode("div", "flex: 1 1 150px; margin: 5px 5px 5px 5px; display: flex; flex-direction: row; flex-wrap: nowrap; overflow: hidden; order: 1;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            if (!disabled) {
                activate(!active);
            }
        });
        this.initHideFromNativeCallList = function (initActive, forceSn) {
            force = forceSn;
            active = initActive;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            disable(force);
        };
        this.allow = function (doAllow) {
            allowed = doAllow;
            disable(force || !doAllow);

            if (!force && !doAllow && active) {
                activate(false);
            }
        };
    };
    HideFromNativeCallListFlag.prototype = innovaphone.ui1.nodePrototype;

    function ActiveAfterCloseFlag(owner, lang) {
        var that = this,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); font-size: 14px; margin: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "activeAfterCloseFlagText"),
            active = false,
            force = false;

        this.createNode("div", "flex: 1 1 150px; margin: 5px 5px 5px 10px; display: flex; flex-direction: row; flex-wrap: nowrap; overflow: hidden; order: 1;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            if (force == false) {
                active = !active;
                owner.activateActiveAfterCloseFlag(active);
                checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
                checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            }
        });
        this.initActiveAfterClose = function (initActive, forceSn) {
            force = forceSn;
            active = initActive;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            this.setDisabled(force);
            this.container.style.opacity = force ? "0.5" : null;
        };
    };
    ActiveAfterCloseFlag.prototype = innovaphone.ui1.nodePrototype;

    function ExcludeInterfacesFlag(owner, lang) {
        var that = this,
            inputName = new innovaphone.ui1.Input("flex:0 1 auto; min-width:74px; padding: 0px 10px 0px 10px; max-width:300px; overflow:hidden; margin:10px; outline: none; border-color: var(--c2); height:34px; color: var(--c2); background-color: var(--hotkey-bg); border:1px solid; box-shadow:none; cursor:pointer; font-size:14px; display: flex").addTranslation(lang, "excludeInterfacesExample", "placeholder"),
            active = false,
            force = false;

        this.createNode("div", "display: flex; flex-direction: row; flex-wrap: wrap; margin-left: 5px; overflow: hidden; font-size: 14px; text-align:center; color: var(--c1);");
        this.add(inputName);
        this.initExcludeInterfaces = function (initActive, forceSn) {
            if (initActive === undefined || initActive == null || initActive == "") {
                active = false;
                this.container.style.display = "none";
            }
            else {
                active = true;
                force = forceSn;
                inputName.container.value = initActive;
                this.setDisabled(force);
                this.container.style.display = "flex";
            }
            owner.activateExcludeInterfacesFlag(active);
        };
    };
    ExcludeInterfacesFlag.prototype = innovaphone.ui1.nodePrototype;

    function DisableOutlookSearchFlag(owner, lang) {
        var that = this,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 auto; color: var(--c1); font-size: 14px; line-height: 20px; margin: 0 8px 0 4px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "disableOutlookSearchFlagText"),
            active = false,
            force = false;

        this.createNode("button", "flex: 1 1 150px; margin: 0 8px 0 4px; padding: 0; text-align: left; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; border-radius: 5px; overflow: hidden;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            if (force == false) {
                active = !active;
                owner.activateDisableOutlookSearchFlag(active);
                checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
                checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            }
        });
        this.initDisableOutlookSearch = function (initActive, forceSn) {
            force = forceSn;
            active = initActive;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            this.setDisabled(force);
            this.container.style.opacity = force ? "0.5" : null;
        };
    };
    DisableOutlookSearchFlag.prototype = innovaphone.ui1.nodePrototype;

    function Checkbox(lang, textId, callback) {
        var that = this,
            checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); font-size: 14px; margin: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, textId),
            active = 0;

        this.createNode("div", "flex: 1 1 150px; margin: 5px 5px 5px 10px; display: flex; flex-direction: row; flex-wrap: nowrap; overflow: hidden; order: 1;");
        this.add(checkbox);
        this.add(title);
        this.addEvent("click", function (e) {
            active = !active;
            callback(active);
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
        });
        this.set = function (active) {
            this.active = active;
            checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
            checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
        };
    };
    Checkbox.prototype = innovaphone.ui1.nodePrototype;

    PageHotkeys.HotkeyButtonKey = function (style, clickHotkey, lang, value, keyValue, optional) {
        var hotkeyButtonKey = this,
            active = false;
        this.createNode("input", style, null, null);
        this.setNoSelect();
        this.container.setAttribute("type", "submit");
        this.container.setAttribute("value", keyValue);
        this.addEvent("click", clickHotkeyButtonKey);

        function clickHotkeyButtonKey() {
            console.log("clickHotkeyButtonKey key=" + value + " optional=" + optional + " active=" + active);
            if (active) {
                active = false;
                hotkeyButtonKey.container.style.backgroundColor = "var(--main-bg)";
                hotkeyButtonKey.container.style.fill = "var(--main-bg)";
                clickHotkey(value, optional, false);
            }
            else {
                // This will be changed in setHotkey when the confirmation from the client is received
                //active = true;
                //hotkeyButtonKey.container.style.backgroundColor = "var(--yellow)";
                //hotkeyButtonKey.container.style.fill = "var(--yellow)";
                clickHotkey(value, optional, true);
            }
        }

        function setHotkey() {
            console.log("setHotkey keyValue=" + keyValue + " value=" + value + " active=" + active);
            active = true;
            hotkeyButtonKey.container.style.backgroundColor = "var(--yellow)";
            hotkeyButtonKey.container.style.fill = "var(--yellow)";
        }

        function unsetHotkey() {
            //console.log("unsetHotkey keyValue=" + keyValue + " value=" + value + " active=" + active);
            active = false;
            hotkeyButtonKey.container.style.backgroundColor = "var(--main-bg)";
            hotkeyButtonKey.container.style.fill = "var(--main-bg)";
        }

        function getKey() {
            return value;
        }

        this.getKey = getKey;
        this.setHotkey = setHotkey;
        this.unsetHotkey = unsetHotkey;
    }
    PageHotkeys.HotkeyButtonKey.prototype = innovaphone.ui1.nodePrototype;

    PageHotkeys.SelectHotkeyButton = function (style, value, setHotkey, checkOtherHotkeys, clearError, lang, display) {
        var selectHotkeyButton = this,
            force = false,
            selectedMandatoryKey = -1,
            selectedOptionalKey1 = -1,
            selectedOptionalKey2 = -1,
            functionKey = new innovaphone.ui1.Node("div", "flex: 1 1 230px; margin: 5px 5px 5px 5px; display: flex; flex-direction: row; flex-wrap: nowrap; order: 1;"),
            additionalKey = new innovaphone.ui1.Node("div", "flex: 1 1 230px; margin: 5px 5px 5px 5px; display: flex; flex-direction: row; flex-wrap: nowrap; order: 1;"),
            functionColKey = new innovaphone.ui1.Node("div", "flex: 1 1 230px;"),
            functionColRowKey = new innovaphone.ui1.Node("div", "display: flex; flex-direction: row; flex-wrap: wrap; overflow: hidden; order: 1;"),
            additionalColKey = new innovaphone.ui1.Node("div", "flex: 1 1 230px;"),
            additionalColRowKey = new innovaphone.ui1.Node("div", "display: flex; flex-direction: row; flex-wrap: wrap; overflow: hidden; order: 1;"),
            fKey = new innovaphone.ui1.Node("div", "flex: 1 1 30px; min-height: 34px; color: var(--c2); font-size: 14px;").addTranslation(lang, "selectFunctionKey"),
            fKey1 = new innovaphone.ui1.Node("div", "flex: 1 1 60px; color: var(--c1); font-size: 14px; white-space: nowrap; text-overflow: ellipsis;"),
            addFKey = new innovaphone.ui1.Node("div", "flex: 1 1 30px; min-height: 34px; color: var(--c2); font-size: 14px;").addTranslation(lang, "selectAdditionalFunctionKey"),
            addFKey1 = new innovaphone.ui1.Node("div", "flex: 1 1 30px; color: var(--c1); font-size: 14px; white-space: nowrap; text-overflow: ellipsis;"),
            title = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); font-size: 14px; margin: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, name),
            fkeys = new Array("F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11"),
            mods, modsC,
            hotkeys = [],
            optHotkeys = [],
            visible = false;

        if(navigator.platform.indexOf("MacIntel") != -1) {
            mods = new Array("opt", "ctrl", "shift", "cmd");
            modsC = new Array("OPT", "CTRL", "SHIFT", "CMD");
        }
        else {
            mods = new Array("alt", "ctrl", "shift", "win");
            modsC = new Array("ALT", "CTRL", "SHIFT", "WIN");
        }
        
        functionColKey.add(fKey);
        for (var i = 0; i < fkeys.length; i++) {
            hotkeys[i] = new PageHotkeys.HotkeyButtonKey("flex: 1 1 60px; max-width: 60px; width: 60px; height: 26px; line-height: 26px; border-radius: 13px; background-color: var(--main-bg); color: var(--c1); font-size: 14px; margin: 5px; padding: 0; text-overflow: ellipsis; white-space: nowrap;", clickHotkey, lang, i, fkeys[i], false);
            hotkeys[i].testId(value + "-" + fkeys[i]);
            functionColRowKey.add(hotkeys[i]);
        }
        fKey1.add(functionColRowKey);
        functionColKey.add(fKey1);
        functionKey.add(functionColKey);

        additionalColKey.add(addFKey);
        for (var i = 0; i < mods.length; i++) {
            optHotkeys[i] = new PageHotkeys.HotkeyButtonKey("flex: 1 1 60px; max-width: 60px; width: 60px; height: 26px; line-height: 26px; border-radius: 13px; background-color: var(--main-bg); color: var(--c1); font-size: 14px; margin: 5px; padding: 0; text-overflow: ellipsis; white-space: nowrap;", clickHotkey, lang, i, mods[i], true);
            additionalColRowKey.add(optHotkeys[i]);
        }
        addFKey1.add(additionalColRowKey);
        additionalColKey.add(addFKey1);
        additionalKey.add(additionalColKey);

        this.createNode("div", style, null, null);
        this.add(functionKey);
        this.add(additionalKey);

        this.Show = function () { this.container.style.display = "flex"; visible = true; }
        this.Hide = function () { this.container.style.display = "none"; visible = false; }
        if (display == "hidden") this.Hide();

        function clickHotkey(key, optional, active) {
            if (force === false) {
                console.log("clickHotkey key=" + key + " optional=" + optional + " active=" + active);
                console.log("clickHotkey selectedMandatoryKey=" + selectedMandatoryKey + " selectedOptionalKey1=" + selectedOptionalKey1 + " selectedOptionalKey2=" + selectedOptionalKey2);
                var mandKey = selectedMandatoryKey;
                var optKey1 = selectedOptionalKey1;
                var optKey2 = selectedOptionalKey2;
                if (optional) {
                    if (selectedOptionalKey1 == key) {  // remove optional
                        selectedOptionalKey1 = selectedOptionalKey2;
                        selectedOptionalKey2 = -1;
                    }
                    else if (selectedOptionalKey2 == key) selectedOptionalKey2 = -1; // remove optional 
                    else if (selectedOptionalKey1 == -1) selectedOptionalKey1 = key; // select first optional key
                    else if (selectedOptionalKey2 == -1) {                           // select second optional key
                        if (key < selectedOptionalKey1) {
                            selectedOptionalKey2 = selectedOptionalKey1;
                            selectedOptionalKey1 = key;
                        }
                        else selectedOptionalKey2 = key;
                    }
                    else {
                        for (var i = 0; i < optHotkeys.length; i++) {
                            if (optHotkeys[i].getKey() == selectedOptionalKey2) {
                                optHotkeys[i].unsetHotkey();
                            }
                        }
                        if (key < selectedOptionalKey1) {
                            selectedOptionalKey2 = selectedOptionalKey1;
                            selectedOptionalKey1 = key;
                        }
                        else selectedOptionalKey2 = key;
                    }
                }
                else {
                    for (var i = 0; i < hotkeys.length; i++) {
                        if (hotkeys[i].getKey() != key) hotkeys[i].unsetHotkey();
                        else if (active == false) selectedMandatoryKey = -1;
                    }
                    if (active) selectedMandatoryKey = key;
                }
                var hk = "";
                if (selectedMandatoryKey >= 0) {
                    if (selectedOptionalKey1 >= 0) hk = modsC[selectedOptionalKey1] + " + ";
                    if (selectedOptionalKey2 >= 0) hk += modsC[selectedOptionalKey2] + " + ";
                    hk += fkeys[selectedMandatoryKey];
                    var testHotkeys = checkOtherHotkeys(hk);
                    console.log("checkOtherHotkeys " + testHotkeys);
                    if (testHotkeys == 1) setHotkey(value, hk);
                    else {
                        if (selectedMandatoryKey != -1) hotkeys[selectedMandatoryKey].unsetHotkey();
                        if (mandKey != -1) hotkeys[mandKey].setHotkey();
                        selectedMandatoryKey = mandKey;
                        if (selectedOptionalKey1 != -1) optHotkeys[selectedOptionalKey1].unsetHotkey();
                        if (optKey1 != -1) optHotkeys[optKey1].setHotkey();
                        selectedOptionalKey1 = optKey1;
                        if (selectedOptionalKey2 != -1) optHotkeys[selectedOptionalKey2].unsetHotkey();
                        if (optKey2 != -1) optHotkeys[optKey2].setHotkey();
                        selectedOptionalKey2 = optKey2;
                    }
                }
                else if (optional == false && active == false) setHotkey(value, null);  // only reset if a mandatory was deactivated
                else if (optional == true) {
                    if (selectedOptionalKey1 != -1 && optKey1 == -1) optHotkeys[selectedOptionalKey1].setHotkey();
                    else if (selectedOptionalKey1 == -1 && optKey1 != -1) optHotkeys[optKey1].unsetHotkey();
                    else if (selectedOptionalKey1 != -1 && optKey1 != -1) {
                        if (optKey1 != selectedOptionalKey2) optHotkeys[optKey1].unsetHotkey();
                        optHotkeys[selectedOptionalKey1].setHotkey();
                    }
                    if (selectedOptionalKey2 != -1 && optKey2 == -1) optHotkeys[selectedOptionalKey2].setHotkey();
                    else if (selectedOptionalKey2 == -1 && optKey2 != -1) optHotkeys[optKey2].unsetHotkey();
                    else if (selectedOptionalKey2 != -1 && optKey2 != -1) {
                        if (optKey2 != selectedOptionalKey1) optHotkeys[optKey2].unsetHotkey();
                        optHotkeys[selectedOptionalKey2].setHotkey();
                    }
                    if (active == true) clearError();                                   // remove error if present
                }
            }
        }

        function getHotkeyValue() {
            var hk = "";
            if (selectedMandatoryKey >= 0) {
                if (selectedOptionalKey1 >= 0) hk = modsC[selectedOptionalKey1] + " + ";
                if (selectedOptionalKey2 >= 0) hk += modsC[selectedOptionalKey2] + " + ";
                hk += fkeys[selectedMandatoryKey];
            }
            return hk;
        }

        function initHotkey(hotkey, forceHk) {
            console.log("initHotkey " + hotkey + " selectedMandatoryKey=" + selectedMandatoryKey + " selectedOptionalKey1=" + selectedOptionalKey1 + " selectedOptionalKey2=" + selectedOptionalKey2 + " force=" + forceHk);
            force = forceHk;
            if (hotkey.indexOf("--none--") != -1 || hotkey.indexOf("error_registered") != -1 || (hotkey.indexOf("not_registered") != -1 && selectedMandatoryKey == -1)) {
                for (var i = 0; i < optHotkeys.length; i++) {
                    optHotkeys[i].unsetHotkey();
                }
                for (var i = 0; i < hotkeys.length; i++) {
                    hotkeys[i].unsetHotkey();
                }
                selectedMandatoryKey = selectedOptionalKey1 = selectedOptionalKey2 = -1;
            }
            else {
                for (var i = 0; i < modsC.length; i++) {
                    if (hotkey.indexOf(modsC[i]) != -1) {
                        optHotkeys[i].setHotkey();
                        if (selectedOptionalKey1 == -1) selectedOptionalKey1 = i;
                        else if (selectedOptionalKey1 != i && selectedOptionalKey2 == -1) selectedOptionalKey2 = i;
                    }
                }
                if (hotkey.indexOf(fkeys[9]) != -1) {
                    hotkeys[9].setHotkey();
                    selectedMandatoryKey = 9;
                }
                else if (hotkey.indexOf(fkeys[10]) != -1) {
                    hotkeys[10].setHotkey();
                    selectedMandatoryKey = 10;
                }
                else if (hotkey.indexOf(fkeys[11]) != -1) {
                    hotkeys[11].setHotkey();
                    selectedMandatoryKey = 11;
                }
                else {
                    for (var i = 0; i < 9; i++) {
                        if (hotkey.indexOf(fkeys[i]) != -1) {
                            hotkeys[i].setHotkey();
                            selectedMandatoryKey = i;
                            break;
                        }
                    }
                }
            }
        }
        this.getHotkeyValue = getHotkeyValue;
        this.initHotkey = initHotkey;
    }
    PageHotkeys.SelectHotkeyButton.prototype = innovaphone.ui1.nodePrototype;

    PageHotkeys.HotkeyButton = function (style, showMenu, lang, value, hotkeyStr) {
        var active = false;
        var force = false;
        var hotkeyButton0 = new innovaphone.ui1.Input(style + "display: flex;").testId(hotkeyStr);
        var hotkeyAddIcon0 = new innovaphone.ui1.SvgInline("flex: 0 0 auto; height:24px; width:12px; fill:var(--c1); pointer-events: none; display: none", icons.add.viewbox, icons.add.code);
        var hotkeyButton1 = new innovaphone.ui1.Input(style + "display: none;");
        var hotkeyAddIcon1 = new innovaphone.ui1.SvgInline("flex: 0 0 auto; padding-top: 12px; height:24px; width:12px; fill:var(--c1); pointer-events: none; display: none", icons.add.viewbox, icons.add.code);
        var hotkeyButton2 = new innovaphone.ui1.Input(style + "display: none;");
        var fkeys = new Array("F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11");
        var modsC;
        if (navigator.platform.indexOf("MacIntel") != -1) {
            modsC = new Array("OPT", "CTRL", "SHIFT", "CMD");
        }
        else {
            modsC = new Array("ALT", "CTRL", "SHIFT", "WIN");
        }
        hotkeyButton0.setNoSelect();
        hotkeyButton0.container.setAttribute("type", "submit");
        hotkeyButton1.setNoSelect();
        hotkeyButton1.container.setAttribute("type", "submit");
        hotkeyButton2.setNoSelect();
        hotkeyButton2.container.setAttribute("type", "submit");
        hotkeyButton0.addTranslation(lang, value, "value");

        this.createNode("div", "display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; overflow: hidden; font-size: 14px; text-align:center; color: var(--c1);", null, null);
        this.add(hotkeyButton0);
        this.add(hotkeyAddIcon0);
        this.add(hotkeyButton1);
        this.add(hotkeyAddIcon1);
        this.add(hotkeyButton2);
        this.addEvent("click", clickHotkeyButton);

        this.setText = function (hotkey) {
            hotkeyAddIcon0.container.style.display = "none";
            hotkeyButton1.container.style.display = "none";
            hotkeyAddIcon1.container.style.display = "none";
            hotkeyButton2.container.style.display = "none";

            if (hotkey) {
                hotkeyButton0.container.style.paddingLeft = "20px";

                var searchStr = hotkey;
                var setHotkeyButton = hotkeyButton0;
                for (var i = 0; i < modsC.length; i++) {
                    if (searchStr.indexOf(modsC[i]) != -1) {
                        setHotkeyButton.container.setAttribute("value", modsC[i]);
                        if(setHotkeyButton == hotkeyButton0) {
                            hotkeyAddIcon0.container.style.display = "flex";
                            hotkeyButton1.container.style.display = "flex";
                            setHotkeyButton = hotkeyButton1;
                        }
                        else {
                            hotkeyAddIcon1.container.style.display = "flex";
                            hotkeyButton2.container.style.display = "flex";
                            setHotkeyButton = hotkeyButton2;
                        }
                        searchStr = searchStr.substr(modsC[i].length);
                    }
                }
                if (searchStr.indexOf(fkeys[9]) != -1) {
                    setHotkeyButton.container.setAttribute("value", fkeys[9]);
                    setHotkeyButton.container.style.display = "flex";
                }
                else if (searchStr.indexOf(fkeys[10]) != -1) {
                    setHotkeyButton.container.setAttribute("value", fkeys[10]);
                    setHotkeyButton.container.style.display = "flex";
                }
                else if (searchStr.indexOf(fkeys[11]) != -1) {
                    setHotkeyButton.container.setAttribute("value", fkeys[11]);
                    setHotkeyButton.container.style.display = "flex";
                }
                else {
                    for (var i = 0; i < 9; i++) {
                        if (searchStr.indexOf(fkeys[i]) != -1) {
                            setHotkeyButton.container.setAttribute("value", fkeys[i]);
                            setHotkeyButton.container.style.display = "flex";
                            break;
                        }
                    }
                }
            }
            else {
                hotkeyButton0.container.style.paddingLeft = "10px";
                hotkeyButton0.container.style.Color = "var(--c2)";
                hotkeyButton0.addTranslation(lang, value, "value");
            }
        }

        function clickHotkeyButton() {
            if (force === false) {
                if (active) {
                    active = false;
                    hotkeyButton0.container.style.borderColor = "var(--c2)";
                    hotkeyButton1.container.style.borderColor = "var(--c2)";
                    hotkeyButton2.container.style.borderColor = "var(--c2)";
                    hotkeyButton0.container.style.Color = "var(--c2)";
                    hotkeyButton1.container.style.Color = "var(--c2)";
                    hotkeyButton2.container.style.Color = "var(--c2)";
                }
                else {
                    active = true;
                    hotkeyButton0.container.style.Color = "var(--c1)";
                    hotkeyButton1.container.style.Color = "var(--c1)";
                    hotkeyButton2.container.style.Color = "var(--c1)";
                }
                showMenu();
            }
        }

        function initHotkey(hotkey, forceHk) {
            force = forceHk;
            hotkeyAddIcon0.container.style.display = "none";
            hotkeyButton1.container.style.display = "none";
            hotkeyAddIcon1.container.style.display = "none";
            hotkeyButton2.container.style.display = "none";

            if (hotkey == "--none--" || hotkey.indexOf("--not_registered--") != -1 || hotkey.indexOf("--error_") != -1) {
                hotkeyButton0.container.style.borderColor = "var(--c2)";
                hotkeyButton0.container.style.Color = "var(--c2)";
                hotkeyButton0.addTranslation(lang, value, "value");
            }
            else {
                hotkeyButton0.container.style.borderColor = "var(--yellow)";
                hotkeyButton0.container.style.Color = "var(--c1)";

                var searchStr = hotkey;
                var index = 0;
                var setHotkeyButton = hotkeyButton0;
                for (var i = 0; i < modsC.length; i++) {
                    if (searchStr.indexOf(modsC[i]) != -1) {
                        setHotkeyButton.container.setAttribute("value", modsC[i]);
                        if(setHotkeyButton == hotkeyButton0) {
                            hotkeyAddIcon0.container.style.display = "flex";
                            hotkeyButton1.container.style.borderColor = "var(--yellow)";
                            hotkeyButton1.container.style.Color = "var(--c1)";
                            hotkeyButton1.container.style.display = "flex";
                            setHotkeyButton = hotkeyButton1;
                        }
                        else {
                            hotkeyAddIcon1.container.style.display = "flex";
                            hotkeyButton2.container.style.borderColor = "var(--yellow)";
                            hotkeyButton2.container.style.Color = "var(--c1)";
                            hotkeyButton2.container.style.display = "flex";
                            setHotkeyButton = hotkeyButton2;
                        }
                        searchStr = searchStr.substr(modsC[i].length);
                    }
                }
                if (searchStr.indexOf(fkeys[9]) != -1) {
                    setHotkeyButton.container.setAttribute("value", fkeys[9]);
                    setHotkeyButton.container.style.display = "flex";
                }
                else if (searchStr.indexOf(fkeys[10]) != -1) {
                    setHotkeyButton.container.setAttribute("value", fkeys[10]);
                    setHotkeyButton.container.style.display = "flex";
                }
                else if (searchStr.indexOf(fkeys[11]) != -1) {
                    setHotkeyButton.container.setAttribute("value", fkeys[11]);
                    setHotkeyButton.container.style.display = "flex";
                }
                else {
                    for (var i = 0; i < 9; i++) {
                        if (searchStr.indexOf(fkeys[i]) != -1) {
                            setHotkeyButton.container.setAttribute("value", fkeys[i]);
                            setHotkeyButton.container.style.display = "flex";
                            break;
                        }
                    }
                }
            }
        }

        this.initHotkey = initHotkey;
    };
    PageHotkeys.HotkeyButton.prototype = innovaphone.ui1.nodePrototype;

    PageHotkeys.Hotkey = function (owner, lang, value, appLink, valueLang) {
        var visible = false,
            hotkeyClass = this,
            hotkeyButton = new PageHotkeys.HotkeyButton("flex:0 1 auto; min-width:74px; padding: 0px 20px; max-width:300px; text-overflow:ellipsis; margin:10px; border-color: var(--c2); height:34px; border-radius:17px; color: var(--c2); text-align:center; border:1px solid; box-shadow:none; cursor:pointer; font-size:14px;", showMenu, lang, "noHotkeySelected", value),
            selectHotkeyButton = new PageHotkeys.SelectHotkeyButton("display: flex; flex-direction: row; flex-wrap: wrap; padding: 0px; margin: 5px; overflow: hidden;", value, setHotkey, checkOtherHotkeys, clearError, lang, "hidden"),
            inputNameText = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c1); margin-left: 10px; margin-top: 15px;").addTranslation(lang, "addAppLinkText"),
            inputNameDiv = new innovaphone.ui1.Node("div", "position:relative; max-width: 500px;margin-right:15px;margin-bottom: 5px; "),
            inputName = new innovaphone.ui1.Input("margin-left: 10px; margin-top: 5px; padding-left: 10px;height: 32px; border-radius:16px; box-sizing:border-box; border: 0em; width:100%; background-color: var(--search-bg); color: var(--c2); text-overflow: ellipsis;").addTranslation(lang, "addAppLink", "placeholder"),
            errorSettingHotkey = null,
            keyValue = null;
        
        const style = "font-size: 16px; color: var(--c1); background-color: var(--hotkey-bg); border-radius: var(--border-radius); margin-left: 15px; margin-top: 10px; margin-right: 15px; padding: 5px;";
        this.createNode("div", style, null, null);

        if (appLink) {
            this.add(new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c1); margin-left: 10px; margin-top: 10px; ").addTranslation(lang, valueLang));
            this.add(inputNameText);
            inputNameDiv.add(inputName);
            this.add(inputNameDiv);
        }
        else {
            this.add(new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c1); margin-left: 10px; margin-top: 10px; ").addTranslation(lang, value));
        }
        this.add(hotkeyButton);
        this.add(selectHotkeyButton);

        function updateAppLink(e) {
            var changed = inputName.changed();
            console.log("updateAppLink changed=" + inputName.changed() + " value=" + inputName.getValue(true) + " keyValue=" + keyValue);
            if (keyValue && keyValue != "" && keyValue != "--none--") {
                var newValue = inputName.getValue(true);
                if (newValue !== undefined && newValue != null && newValue != "") {
                    if (value == "hotkeyAppLink0") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink0": { "value": keyValue, "appLink": newValue, "force": false } } });
                    else if (value == "hotkeyAppLink1") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink1": { "value": keyValue, "appLink": newValue, "force": false } } });
                    else if (value == "hotkeyAppLink2") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink2": { "value": keyValue, "appLink": newValue, "force": false } } });
                }
                else {
                    if (value == "hotkeyAppLink0") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink0": { "value": "--none--", "force": false } } });
                    else if (value == "hotkeyAppLink1") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink1": { "value": "--none--", "force": false } } });
                    else if (value == "hotkeyAppLink2") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink2": { "value": "--none--", "force": false } } });
                    keyValue = null;
                }
            }
        }

        inputName.container.addEventListener("input", updateAppLink);

        function showMenu() {
            if (visible) {
                selectHotkeyButton.Hide();
                visible = false;
                if (errorSettingHotkey != null) hotkeyClass.rem(errorSettingHotkey);
                errorSettingHotkey = null;
            }
            else {
                selectHotkeyButton.Show();
                visible = true;
            }
        }

        function checkOtherHotkeys(hotkey) {
            return owner.checkOtherHotkeys(value, hotkey);
        }

        function setHotkey(hotkeyType, key) {
            console.log("setHotkey " + hotkeyType + " key=" + key);
            if (errorSettingHotkey) hotkeyClass.rem(errorSettingHotkey);
            errorSettingHotkey = null;
            if (key) {
                //hotkeyButton.setText(key);
                if (hotkeyType == "hotkeyDial") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyDial": { "value": key, "force": false }}});
                else if (hotkeyType == "hotkeyAccept") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAccept": { "value": key, "force": false }}});
                else if (hotkeyType == "hotkeyReject") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyReject": { "value": key, "force": false } } });
                else if (hotkeyType == "hotkeyAppLink0") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink0": { "value": key, "appLink": inputName.getValue(true), "force": false } } });
                else if (hotkeyType == "hotkeyAppLink1") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink1": { "value": key, "appLink": inputName.getValue(true), "force": false } } });
                else if (hotkeyType == "hotkeyAppLink2") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink2": { "value": key, "appLink": inputName.getValue(true), "force": false } } });
                keyValue = key;
            }
            else {
                //hotkeyButton.setText(null);
                if (hotkeyType == "hotkeyDial") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyDial": { "value": "--none--", "force": false }}});
                else if (hotkeyType == "hotkeyAccept") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAccept": { "value": "--none--", "force": false }}});
                else if (hotkeyType == "hotkeyReject") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyReject": { "value": "--none--", "force": false }}});
                else if (hotkeyType == "hotkeyAppLink0") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink0": { "value": "--none--", "force": false } } });
                else if (hotkeyType == "hotkeyAppLink1") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink1": { "value": "--none--", "force": false } } });
                else if (hotkeyType == "hotkeyAppLink2") owner.sendHotkey({ mt: "ClientConfig", adminSettings: { "hotkeyAppLink2": { "value": "--none--", "force": false } } });
                inputName.setValue("", false);
                keyValue = null;
            }
        }

        function clearError() {
            if (errorSettingHotkey) hotkeyClass.rem(errorSettingHotkey);
            errorSettingHotkey = null;
        }

        function setError(error) {
            clearError();
            errorSettingHotkey = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--red); margin: 10px; padding: 5px;").addTranslation(lang, error);
            this.add(errorSettingHotkey);
        }

        function getHotkeyValue() {
            return selectHotkeyButton.getHotkeyValue();
        }

        function getHotkeyAppLink() {
            return inputName.getValue(true);
        }

        function initHotkey(hotkey, force, appLink) {
            hotkeyButton.initHotkey(hotkey, force);
            selectHotkeyButton.initHotkey(hotkey, force);
            if (visible == true && hotkey.indexOf("error") != -1) {
                clearError();
                errorSettingHotkey = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--red); margin: 10px; padding: 5px;").addTranslation(lang, "errorSettingHotkey");
                this.add(errorSettingHotkey);
            }
            this.setDisabled(force);
            this.container.style.opacity = force ? "0.5" : null;
            if (appLink != "" && appLink !== undefined) inputName.setValue(appLink);
            keyValue = hotkey;
        }

        this.initHotkey = initHotkey;
        this.getHotkeyValue = getHotkeyValue;
        this.getHotkeyAppLink = getHotkeyAppLink;
        this.setError = setError;
        this.clearError = clearError;
    }
    PageHotkeys.Hotkey.prototype = innovaphone.ui1.nodePrototype;

    function PageSettings(owner, lang, send) {
        var that = this,
            title = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "settings"),
            autostart = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px 0px 0px 10px; padding: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "autostart"),
            offline = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 20px 0px 0px 10px; padding: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "offline"),
            contentOffline = new innovaphone.ui1.Node("div", "display: flex; flex-direction: row; flex-wrap: wrap; padding: 0px; margin: 0px 0px 0px 10px; overflow: hidden;"),
            docking = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 25px 0px 0px 15px;").addTranslation(lang, "docking"),
            contentDocking = new innovaphone.ui1.Node("div", "display: flex; flex-direction: row; flex-wrap: wrap; padding: 0px; margin: 0px 0px 0px 5px; overflow: hidden;"),
            showNotifications = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "desktopNotifications"),
            noVpnAddresses = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "noVpnAddressesText"),
            activeAfterClose = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "activeAfterCloseText"),
            disableOutlookSearch = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "disableOutlookSearchText"),
            excludeInterfaces = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "excludeInterfacesText");

        var dockingFlags = [];
        this.activateDockingFlag = function (id) {
            console.log("activateDockingFlag " + id);
            dockingFlags.forEach(function (e) { e.setActiveId(id); });
            send({ mt: "ClientConfig", adminSettings: { "docking": { "value": id, "force": false }}});
        };
        var offlineFlags = [];
        this.activateOfflineFlag = function (id) {
            console.log("activateOfflineFlag " + id);
            offlineFlags.forEach(function (e) { e.setActiveId(id); });
            var offline = 0;
            if (id == 1)
                offline = 60000;
            else if (id == 2)
                offline = 300000;
            else if (id == 3)
                offline = 600000;
            else if (id == 4)
                offline = 900000;            
            send({ mt: "ClientConfig", adminSettings: { "offline": { "value": offline, "force": false }}});
        };
        this.activateAutostartFlag = function (flag) {
            console.log("activateAutostartFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "autostart": { "value": flag, "force": false }}});
        };

        this.activateShowDesktopNotificationsFlag = function (flag) {
            console.log("activateShowDesktopNotificationsFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "showDesktopNotifications": { "value": flag, "force": false }}});
        };

        this.activateNoVpnAddressesFlag = function (flag) {
            console.log("activateNoVpnAddressesFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "noVpnAddresses": { "value": flag, "force": false } } });
        };

        this.activateActiveAfterCloseFlag = function (flag) {
            console.log("activateActiveAfterCloseFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "activeAfterClose": { "value": flag, "force": false } } });
        };

        this.activateDisableOutlookSearchFlag = function (flag) {
            console.log("activateDisableOutlookSeachFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "disableOutlookSearch": { "value": flag, "force": false } } });
        };

        this.activateExcludeInterfacesFlag = function (active) {
            if (active) {
                if (navigator.platform.indexOf("Win") != -1) {
                    excludeInterfaces.container.style.display = "flex";
                }
            }
            else {
                if (navigator.platform.indexOf("Win") != -1) {
                    excludeInterfaces.container.style.display = "none";
                }
            }
        };

        function OfflineFlag(owner, name, id) {
            var that = this,
                active = false,
                force = false,
                radioButton = new innovaphone.ui1.SvgInline("flex: 0 0 auto; margin:5px; border: 0.5px solid; border-color: var(--radio-border); border-radius: 50%; width: 16px; height: 16px; background-color: var(--content-bg); fill: var(--content-bg); cursor: pointer;", icons.offline.viewbox, icons.offline.code),
                title = new innovaphone.ui1.Node("div", "flex:1 1 auto; color:var(--c1); font-size:14px; margin:0 5px; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;").addTranslation(lang, name);

            this.createNode("button", "flex:1 1 110px; max-width:110px; margin:2px; padding:0; text-align:left; border-radius:5px; display:flex; flex-direction:row; flex-wrap:nowrap; align-items:center; overflow:hidden;");
            this.add(radioButton);
            this.add(title);

            this.setActiveId = function (activeId) {
                active = (activeId == id);
                if (active) {
                    radioButton.container.checked = true;
                    radioButton.container.style.fill = "var(--yellow)";
                }
                else {
                    radioButton.container.checked = false;
                    radioButton.container.style.fill = "var(--content-bg)";
                }
            }

            this.setForceValue = function (forceRb) {
                radioButton.container.disabled = forceRb !== false;
                this.container.style.opacity = forceRb ? "0.5" : null;
                force = forceRb;
            }

            this.container.addEventListener("click", function () {
                if (force === false) owner.activateOfflineFlag(id);
            });
        }
        OfflineFlag.prototype = innovaphone.ui1.nodePrototype;

        var item = new OfflineFlag(that, "never", 0);
        offlineFlags.push(item);
        contentOffline.add(item);
        item = new OfflineFlag(that, "after1Minute", 1);
        offlineFlags.push(item);
        contentOffline.add(item);
        item = new OfflineFlag(that, "after5Minutes", 2);
        offlineFlags.push(item);
        contentOffline.add(item);
        item = new OfflineFlag(that, "after10Minutes", 3);
        offlineFlags.push(item);
        contentOffline.add(item);
        item = new OfflineFlag(that, "after15Minutes", 4);
        offlineFlags.push(item);
        contentOffline.add(item);

        function DockingFlag(owner, name, id) {
            var that = this,
                active = false,
                force = false,
                radioButton = new innovaphone.ui1.SvgInline("flex: 0 0 auto; margin:5px; border: 0.5px solid; border-color: var(--radio-border); border-radius: 50%; width: 16px; height: 16px; background-color: var(--content-bg); fill: var(--content-bg); cursor: pointer;", icons.offline.viewbox, icons.offline.code),
                title = new innovaphone.ui1.Node("div", "flex:1 1 auto; color:var(--c1); font-size:14px; margin:0 5px; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;").addTranslation(lang, name);

            this.createNode("button", "flex:1 1 160px; max-width:160px; margin:2px; padding:0; text-align:left; border-radius:5px; display:flex; flex-direction:row; flex-wrap:nowrap; align-items:center; overflow:hidden;");
            this.add(radioButton);
            this.add(title);

            this.setActiveId = function (activeId) {
                active = (activeId == id);
                if (active) {
                    radioButton.container.checked = true;
                    radioButton.container.style.fill = "var(--yellow)";
                }
                else {
                    radioButton.container.checked = false;
                    radioButton.container.style.fill = "var(--content-bg)";
                }
            }

            this.setForceValue = function (forceRb) {
                radioButton.container.disabled = forceRb !== false;
                this.container.style.opacity = forceRb ? "0.5" : null;
                force = forceRb;
            }

            this.container.addEventListener("click", function () {
                if (force === false) owner.activateDockingFlag(id);
            });
        }
        DockingFlag.prototype = innovaphone.ui1.nodePrototype;

        var item = new DockingFlag(that, "normalWindow", 0);
        dockingFlags.push(item);
        contentDocking.add(item);
        var item = new DockingFlag(that, "dockingLeft", 1);
        dockingFlags.push(item);
        contentDocking.add(item);
        var item = new DockingFlag(that, "dockingRight", 2);
        dockingFlags.push(item);
        contentDocking.add(item);

        var auto = new AutostartFlag(that, lang);
        var desktopNotifications = new NotificationsFlag(that, lang);
        var noVpnAddressesFlag = new NoVpnAddressesFlag(that, lang);
        var activeAfterCloseFlag = new ActiveAfterCloseFlag(that, lang);
        var disableOutlookSearchFlag = new DisableOutlookSearchFlag(that, lang);
        var excludeInterfacesFlag = new ExcludeInterfacesFlag(that, lang);

        this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; padding: 5px; overflow: auto;");
        this.add(autostart);
        this.add(auto);
        this.add(offline);
        this.add(contentOffline);
        if (navigator.platform.indexOf("Win") != -1) {
            this.add(docking);
            this.add(contentDocking);
        }
        this.add(showNotifications);
        this.add(desktopNotifications);
        this.add(noVpnAddresses);
        this.add(noVpnAddressesFlag);
        if (navigator.platform.indexOf("Win") != -1) {
            this.add(excludeInterfaces);
            this.add(excludeInterfacesFlag);
        }
        if (navigator.platform.indexOf("MacIntel") != -1) {
            this.add(activeAfterClose);
            this.add(activeAfterCloseFlag);
        }
        if (navigator.platform.indexOf("Win") != -1) {
            this.add(disableOutlookSearch);
            this.add(disableOutlookSearchFlag);
        }

        owner.onmessage.attach(function (sender, obj) {
            if (obj.mt == "ClientConfig") {
                var offline = obj.offline;
                if (offline !== undefined) {
                    var value = offline.value;
                    var force = offline.force;
                    if (value === 0) offlineFlags[0].setActiveId(0);
                    else if (value === 60000) offlineFlags[1].setActiveId(1);
                    else if (value === 300000) offlineFlags[2].setActiveId(2);
                    else if (value === 600000) offlineFlags[3].setActiveId(3);
                    else if (value === 900000) offlineFlags[4].setActiveId(4);
                    for (var i = 0; i < 5; i++) offlineFlags[i].setForceValue(force);
                    //contentOffline.setDisabled(force);
                }
                if (obj.autostart !== undefined) {
                    var autostart = obj.autostart;
                    auto.initAutostart(autostart.value, autostart.force);
                }
                if (obj.docking !== undefined) {
                    var docking = obj.docking;
                    if (docking.value === 0) dockingFlags[0].setActiveId(0);
                    else if (docking.value === 1) dockingFlags[1].setActiveId(1);
                    else if (docking.value === 2) dockingFlags[2].setActiveId(2);
                    for (var i = 0; i < 3; i++) dockingFlags[i].setForceValue(docking.force);
                }
                if (obj.showDesktopNotifications !== undefined) {
                    var showDesktopNotifications = obj.showDesktopNotifications;
                    desktopNotifications.initNotifications(showDesktopNotifications.value, showDesktopNotifications.force);
                }
                if (obj.noVpnAddresses !== undefined) {
                    var noVpnAddressesVar = obj.noVpnAddresses;
                    noVpnAddressesFlag.initNoVpnAddresses(noVpnAddressesVar.value, noVpnAddressesVar.force);
                }
                if (obj.activeAfterClose !== undefined) {
                    var activeAfterCloseVar = obj.activeAfterClose;
                    activeAfterCloseFlag.initActiveAfterClose(activeAfterCloseVar.value, activeAfterCloseVar.force);
                }
                if (obj.disableOutlookSearch !== undefined) {
                    var disableOutlookSearchVar = obj.disableOutlookSearch;
                    disableOutlookSearchFlag.initDisableOutlookSearch(disableOutlookSearchVar.value, disableOutlookSearchVar.force);
                }
                if (obj.excludeInterfaces !== undefined) {
                    var excludeInterfacesVar = obj.excludeInterfaces;
                    excludeInterfacesFlag.initExcludeInterfaces(excludeInterfacesVar.value, excludeInterfacesVar.force);
                }
            }
        });
    }
    PageSettings.prototype = innovaphone.ui1.nodePrototype;

    function PageIOSSettings(owner, lang, send) {
        var that = this,
            title = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "settings"),
            audioSettingsTitle = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-left: 10px; margin-top: 10px; padding: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;").addTranslation(lang, "audioSettings"),
            ringInHeadset = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "ringHeadset"),
            noVpnAddresses = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "noVpnAddressesText"),
            hideFromNativeCallList = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "hideFromNativeCallList");

        this.activateRingInHeadsetFlag = function (flag) {
            console.log("activateRingInHeadsetFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "ringInHeadset": { "value": flag, "force": false } } });
        };
        var ringInHeadsetFlag = new RingInHeadsetFlag(that, lang);
        this.activateNoVpnAddressesFlag = function (flag) {
            console.log("activateNoVpnAddressesFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "noVpnAddresses": { "value": flag, "force": false } } });
        };
        var noVpnAddressesFlag = new NoVpnAddressesFlag(that, lang);
        this.activateHideFromNativeCallListFlag = function (flag) {
            console.log("activateHideFromNativeCallListFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "hideFromNativeCallList": { "value": flag, "force": false } } });
        };
        var hideFromNativeCallListFlag = new HideFromNativeCallListFlag(that, lang);

        this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; padding: 5px; overflow: auto;");
        this.add(title);
        this.add(audioSettingsTitle);
        this.add(ringInHeadset);
        this.add(ringInHeadsetFlag);
        this.add(noVpnAddresses);
        this.add(noVpnAddressesFlag);
        this.add(hideFromNativeCallList);
        this.add(hideFromNativeCallListFlag);

        owner.onmessage.attach(function (sender, obj) {
            if (obj.mt == "ClientConfig") {
                if (obj.ringInHeadset !== "ringInHeadset") {
                    var ringInHeadsetVar = obj.ringInHeadset;
                    ringInHeadsetFlag.initRingInHeadset(ringInHeadsetVar.value, ringInHeadsetVar.force);
                }
                if (obj.noVpnAddresses !== "noVpnAddresses") {
                    var noVpnAddressesVar = obj.noVpnAddresses;
                    noVpnAddressesFlag.initNoVpnAddresses(noVpnAddressesVar.value, noVpnAddressesVar.force);
                }
                if (obj.hideFromNativeCallList !== "hideFromNativeCallList") {
                    var hideFromNativeCallListVar = obj.hideFromNativeCallList;
                    hideFromNativeCallListFlag.initHideFromNativeCallList(hideFromNativeCallListVar.value, hideFromNativeCallListVar.force);
                }
            }
        });
    }
    PageIOSSettings.prototype = innovaphone.ui1.nodePrototype;

    function PageSlider(style, value, icon, send, property,max) {
        this.createNode("div", "display:flex; flex-direction:row; overflow:hidden; padding-left:15px; padding-right:15px; " + style);

        var that = this,
            svg = this.add(new innovaphone.ui1.SvgInline("flex:0 0 auto; width:20px; height:20px; fill:var(--c1)", icon.viewbox, icon.code)),
            input = this.add(new innovaphone.ui1.Input("flex:1 1 auto; margin-left:15px", value, null, null, "range"));

        input.setAttribute("min", "0");
        input.setAttribute("max", max || "1000");
        input.addEvent("input", function () {
            var adminSettings = {};
            adminSettings[property] = { "value": getValue(), "force": false };
            send({ mt: "ClientConfig", adminSettings: adminSettings })
        });

        function getValue() { return parseInt(input.getValue()); }
        function setValue(value) { input.setValue(value, true); }
        this.getValue = getValue;
        this.setValue = setValue;
    }
    PageSlider.prototype = innovaphone.ui1.nodePrototype;

    function PageSlider_hour(style, value, send, property) {
        this.createNode("div", "display:flex; flex-direction:row; overflow:hidden; padding-left:15px; padding-right:15px; " + style);

        var that = this,
            txt = this.add(new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); width:20px; height:20px;; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;")),
            input = this.add(new innovaphone.ui1.Input("flex:1 1 auto; margin-left:15px", value, null, null, "range"));
        txt.container.innerHTML = getValue();

        input.setAttribute("min", "0");
        input.setAttribute("max", "23");
        input.addEvent("input", function () {
            var adminSettings = {};
            adminSettings[property] = { "value": getValue(), "force": false };
            send({ mt: "ClientConfig", adminSettings: adminSettings })
            txt.container.innerHTML = getValue();
        });

        function getValue() { return parseInt(input.getValue()); }
        function setValue(value) { input.setValue(value, true); txt.container.innerHTML = value; }
        this.getValue = getValue;
        this.setValue = setValue;
    }
    PageSlider_hour.prototype = innovaphone.ui1.nodePrototype;

    function PageIP270Settings(owner, lang, send) {
        this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; padding: 5px; overflow: auto;");

        var that = this,
            title = this.add(new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;")).addTranslation(lang, "settings"),
            audioSettingsTitle = this.add(new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-left: 10px; margin-top: 10px; padding: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;")).addTranslation(lang, "audioSettings"),
            volumeRinger = this.add(new PageSlider("margin-top:30px", 0, icons.ring, send, "ringerVolume")),
            volumeHandset = this.add(new PageSlider("margin-top:30px", 0, icons.handset, send, "handsetVolume")),
            volumeHandsfree = this.add(new PageSlider("margin-top:30px", 0, icons.speaker, send, "handsfreeVolume")),
            volumeHeadset = this.add(new PageSlider("margin-top:30px", 0, icons.headphone, send, "headsetVolume"));

        this.add(new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-left: 10px; margin-top: 10px; padding: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;")).addTranslation(lang, "TXT_LCD_LIGHT");
        backlightMax = this.add(new PageSlider("margin-top:30px", 0, icons.backlight, send, "backlightMax",100));
        this.add(new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-left: 10px; margin-top: 10px; padding: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;")).addTranslation(lang, "TXT_LCD_LIGHT_OFF");
        backlightIdle = this.add(new PageSlider("margin-top:30px", 0, icons.backlight, send, "backlightIdle",100));
        this.add(new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-left: 10px; margin-top: 10px; padding: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;")).addTranslation(lang, "TXT_ENERGY_SAVING_TIME");
        energySavingStart = this.add(new PageSlider_hour("margin-top:30px", 0, send, "energySavingStart"));
        energySavingStop = this.add(new PageSlider_hour("margin-top:30px", 0,  send, "energySavingStop"));

        owner.onmessage.attach(function (sender, obj) {
            if (obj.mt == "ClientConfig") {
                if (obj.ringerVolume) volumeRinger.setValue(obj.ringerVolume.value);
                if (obj.handsetVolume) volumeHandset.setValue(obj.handsetVolume.value);
                if (obj.handsfreeVolume) volumeHandsfree.setValue(obj.handsfreeVolume.value);
                if (obj.backlightMax) backlightMax.setValue(obj.backlightMax.value);
                if (obj.backlightIdle) backlightIdle.setValue(obj.backlightIdle.value);
                if (obj.energySavingStart) energySavingStart.setValue(obj.energySavingStart.value);
                if (obj.energySavingStop) energySavingStop.setValue(obj.energySavingStop.value);
            }
        });
    }
    PageIP270Settings.prototype = innovaphone.ui1.nodePrototype;

    function PageAndroidSettings(owner, lang, send) {
        var that = this,
            title = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "settings"),
            audioSettings = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); background-color: var(--hotkey-bg); margin: 10px 15px 10px 15px; padding: 5px; overflow: hidden;"),
            audioSettingsTitle = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-left: 10px; margin-top: 10px; padding: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;").addTranslation(lang, "audioSettings"),
            audioSettingsInfo = new innovaphone.ui1.Node("div", "margin-left: 10px; display: inline-flex; align-items: start; gap: 5px;"),
            audioSettingsInfoIcon = new innovaphone.ui1.SvgInline("flex: 0 0 auto;width: 20px;height:20px;fill: var(--c2);pointer-events: none;", icons.info.viewbox, icons.info.code),
            audioSettingsInfoText = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c2);").addTranslation(lang, "audioSettingsInfo"),
            audioSettingsDropdown = new innovaphone.ui1.Node("select", "outline: none; font-size: 14px; color: var(--c1); flex: 0 1 auto; max-width: 250px; height: 30px; background-color: var(--main-bg); border: none; margin: 0px 10px 10px 32px; padding: 5px 0px 5px 10px; cursor: pointer; overflow: hidden;"),
            appstartSettings = new innovaphone.ui1.Node("div", "display: none; font-size: 16px; color: var(--c1); background-color: var(--hotkey-bg); margin: 10px 15px 10px 15px; padding: 5px; overflow: hidden;"),
            appstartSettingsTitle = new innovaphone.ui1.Node("div", "display: none; font-size: 16px; color: var(--c1); margin-left: 10px; margin-top: 10px; padding: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;").addTranslation(lang, "androidAppstartSettings"),
            appstartSettingsInfo = new innovaphone.ui1.Node("div", "margin: 10px; display: flex; align-items: center;"),
            appstartSettingsInfoIcon = new innovaphone.ui1.SvgInline("height:24px; width:12px; min-width:12px; fill:var(--c2); pointer-events: none; align-self: flex-start;", icons.info.viewbox, icons.info.code),
            appstartSettingsInfoText = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c2); padding-left: 10px; padding-top: 4px;").addTranslation(lang, "androidAppstartSettingsInfo"),
            autostartSettingsButtons = [],
            noVpnAddresses = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "noVpnAddressesText"),
            avoidNativeCallScreen = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "avoidNativeCallScreen");
            hideFromNativeCallList = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin: 10px; padding: 5px;").addTranslation(lang, "hideFromNativeCallList");
            advanced = this;

        for(var i = 0; i < 8; i++) {
            autostartSettingsButtons.push(new innovaphone.ui1.Node("button", "display: none; cursor: pointer; background-color: var(--button); color: var(--c1); font-size: 14px; margin: 0px 10px 10px 32px; padding: 10px; text-decoration: none; overflow: hidden;"));
        }

        var noVpnAddressesFlag = new NoVpnAddressesFlag(that, lang);
        var avoidNativeCallScreenFlag = new AvoidNativeCallScreenFlag(that, lang);
        var hideFromNativeCallListFlag = new HideFromNativeCallListFlag(that, lang);

        this.activateNoVpnAddressesFlag = function (flag) {
            console.log("activateNoVpnAddressesFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "noVpnAddresses": { "value": flag, "force": false } } });
        };
        this.activateAvoidNativeCallScreenFlag = function (flag) {
            console.log("activateAvoidNativeCallScreenFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "avoidNativeCallScreen": { "value": flag, "force": false } } });
            hideFromNativeCallList.container.style.opacity = flag ? null : "0.5";
            hideFromNativeCallListFlag.allow(flag);
        };
        this.activateHideFromNativeCallListFlag = function (flag) {
            console.log("activateHideFromNativeCallListFlag " + flag);
            send({ mt: "ClientConfig", adminSettings: { "hideFromNativeCallList": { "value": flag, "force": false } } });
        };

        this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; padding: 5px; overflow: auto;");
        this.add(title);
        this.add(audioSettingsTitle);
        this.add(audioSettings);
        audioSettings.add(audioSettingsInfo);
        audioSettingsInfo.add(audioSettingsInfoIcon);
        audioSettingsInfo.add(audioSettingsInfoText);
        audioSettings.add(audioSettingsDropdown);
        audioSettingsDropdown.addEvent("change", function (e) {
            send({ mt: "ClientConfig", adminSettings: { "audioApi": { "value": e.currentTarget.value, "force": false } } });
        });
        this.add(appstartSettingsTitle);
        this.add(appstartSettings);
        appstartSettings.add(appstartSettingsInfo);
        appstartSettingsInfo.add(appstartSettingsInfoIcon);
        appstartSettingsInfo.add(appstartSettingsInfoText);
        for(var i = 0; i < autostartSettingsButtons.length; i++) {
            appstartSettings.add(autostartSettingsButtons[i]);
        }        
        this.add(noVpnAddresses);
        this.add(noVpnAddressesFlag);
        this.add(avoidNativeCallScreen);
        this.add(avoidNativeCallScreenFlag);
        this.add(hideFromNativeCallList);
        this.add(hideFromNativeCallListFlag);

        owner.onmessage.attach(function (sender, obj) {
            if (obj.mt == "ConfigOptions") {
                while (audioSettingsDropdown.container.options.length > 0) audioSettingsDropdown.container.remove(0);
                (obj.audioApis || []).forEach(function (e) {
                    var option = audioSettingsDropdown.add(new innovaphone.ui1.Node("option", "background-color: var(--main-bg); border: none; flex: 1 1 auto; overflow: hidden; outline: none; color: var(--c1);", e.name));
                    option.container.value = e.id;
                });
            }
            else if (obj.mt == "ClientConfig") {
                if (obj.audioApi) {
                    var audioApiVar = obj.audioApi;
                    for (var i = 0; i < audioSettingsDropdown.container.options.length; i++) {
                        audioSettingsDropdown.container.options[i].selected = audioSettingsDropdown.container.options[i].value == audioApiVar.value ? "true" : undefined;
                    }
                }
                if (obj.noVpnAddresses !== "noVpnAddresses") {
                    var noVpnAddressesVar = obj.noVpnAddresses;
                    noVpnAddressesFlag.initNoVpnAddresses(noVpnAddressesVar.value, noVpnAddressesVar.force);
                }
                if (obj.avoidNativeCallScreen !== "avoidNativeCallScreen") {
                    var avoidNativeCallScreenVar = obj.avoidNativeCallScreen;
                    avoidNativeCallScreenFlag.initAvoidNativeCallScreen(avoidNativeCallScreenVar.value, avoidNativeCallScreenVar.force);
                }
                if (obj.hideFromNativeCallList !== "hideFromNativeCallList") {
                    var hideFromNativeCallListVar = obj.hideFromNativeCallList;
                    hideFromNativeCallListFlag.initHideFromNativeCallList(hideFromNativeCallListVar.value, hideFromNativeCallListVar.force);
                }
                hideFromNativeCallList.container.style.opacity = avoidNativeCallScreenFlag.getValue() ? null : "0.5";
                hideFromNativeCallListFlag.allow(avoidNativeCallScreenFlag.getValue());
            }
            else if (obj.mt == "AutostartSettingsApp" && obj.name) {
                appstartSettingsTitle.container.style.display = "block";
                appstartSettings.container.style.display = "block";
                for(var i = 0; i < autostartSettingsButtons.length; i++) {
                    autostartSettingsButtons[i].container.style.display = "none";
                }
                var names = obj.name.split("\n");
                for(var i = 0; i < names.length; i++)
                {
                    autostartSettingsButtons[i].container.style.display = "block";
                    autostartSettingsButtons[i].container.innerText = names[i];
                    autostartSettingsButtons[i].addEvent("click", function (e) {
                        send({ mt: "StartAutostartSettingsApp", name: e.target.innerText });
                    });
                }
            }
        });
    }
    PageAndroidSettings.prototype = innovaphone.ui1.nodePrototype;

    function PageTrace(owner, lang, send) {
        var that = this,
            buttonStyle = "display: inline-flex; align-items: center; cursor: pointer; background-color: var(--button); margin: 15px; padding: 5px; text-decoration: none; overflow: hidden; border-radius: var(--border-radius)",
            title = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-top: 10px; margin-left: 10px; padding: 5px;").addTranslation(lang, "trace"),
            clear = new innovaphone.ui1.Node("button", buttonStyle, null, "button"),
            clearIcon = new innovaphone.ui1.SvgInline("flex: 0 0 auto; height:20px; width:20px; fill:var(--c2); pointer-events: none; padding:5px;", icons.del.viewbox, icons.del.code),
            clearText = new innovaphone.ui1.Node("div", "flex: 1 1 0; padding: 5px; color: var(--c1); font-size: 14px;").addTranslation(lang, "clear"),
            download = new innovaphone.ui1.Node("button", buttonStyle, null, "button"),
            downloadIcon = new innovaphone.ui1.SvgInline("flex: 0 0 auto; height:20px; width:20px; fill:var(--c2); pointer-events: none; padding:5px;", icons.download.viewbox, icons.download.code),
            downloadText = new innovaphone.ui1.Node("div", "flex: 1 1 0; padding: 5px; color: var(--c1); font-size: 14px;").addTranslation(lang, "download"),
            dmp = new innovaphone.ui1.Node("button", "flex: 1 1 150px; margin: 5px 10px; padding: 0; text-align: left; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; border-radius: 5px; overflow: hidden"),
            dmpCheckbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            dmpTitle = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); font-size: 14px; line-height: 20px; margin: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "disableDmpFiles"),
            dmpActive = false,
            emailLog = new innovaphone.ui1.Node("button", buttonStyle, null, "button"),
            emailLogIcon = new innovaphone.ui1.SvgInline("flex: 0 0 auto; height:20px; width:20px; fill:var(--c2); pointer-events: none; padding:5px;", icons.mail.viewbox, icons.mail.code),
            emailLogText = new innovaphone.ui1.Node("div", "flex: 1 1 0; padding: 5px; color: var(--c1); font-size: 14px;").addTranslation(lang, "emailLog"),
            content = new innovaphone.ui1.Node("div", "display: flex; flex-direction: row; flex-wrap: wrap; padding: 0px; margin: 5px; overflow: hidden;"),
            traceMask = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-top: 10px; margin-left: 10px; padding: 5px;"),
            currentFlags = "0000000000000000",
            numTraceFlags = 0,
            traceFlags = [];

        this.onflagschanged = new innovaphone.lib1.Event(this);
        this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; padding: 5px; overflow: auto;");
        this.add(title);
        clear.addEvent("click", function (e) {
            send({ mt: "ClearLog" });
        });
        clear.add(clearIcon);
        clear.add(clearText);
        this.add(clear);
        this.add(content);
        for (var i = 0; i < 20; i++) content.add(new innovaphone.ui1.Node("div", "flex: 1 1 160px; order: 2;"));
        this.add(traceMask);
        download.addEvent("click", function (e) {
            const a = document.createElement("a");
            a.download = "log.txt";
            a.href = "/client/log";
            a.click();
        });
        download.add(downloadIcon);
        download.add(downloadText);
        this.add(download);
        emailLog.addEvent("click", function (e) {
            send({ mt: "EMailLog" });
        });
        emailLog.add(emailLogIcon);
        emailLog.add(emailLogText);
        this.add(emailLog);

        dmp.addEvent("click", function (e) {
            dmpActive = !dmpActive;
            send({ mt: "ClientConfig", adminSettings: { "disableDmpFiles": { "value": dmpActive, "force": false } } });
            dmpCheckbox.container.style.backgroundColor = dmpActive ? "var(--check-bg)" : "var(--uncheck-bg)";
            dmpCheckbox.container.style.fill = dmpActive ? "var(--check-c)" : "var(--uncheck-bg)";
        });

        dmp.add(dmpCheckbox);
        dmp.add(dmpTitle);
        if (navigator.platform.indexOf("Win") != -1) {
            this.add(dmp);
        }

        this.toggleFlag = function (mask) {
            currentFlags = ("0000000" + Number((parseInt(currentFlags.substring( 0, 8),16) ^ parseInt(mask.substring( 0, 8),16)) >>> 0).toString(16)).substr(-8) +
                           ("0000000" + Number((parseInt(currentFlags.substring( 8,16),16) ^ parseInt(mask.substring( 8,16),16)) >>> 0).toString(16)).substr(-8);
            that.onflagschanged.notify();
            send({ mt: "ClientConfig", adminSettings: { "logFlags": { "value": currentFlags, "force": false }}});
        };

        owner.onmessage.attach(function (sender, obj) {
            if (obj.mt == "LogFlagNames") {
                if (numTraceFlags == 0) {
                    obj.names.forEach(function (e) {
                        traceFlags[numTraceFlags] = new TraceFlag(that, e.name, e.flag);
                        content.add(traceFlags[numTraceFlags]);
                        numTraceFlags++;
                    });
                }
            }
            else if (obj.mt == "ClientConfig") {
                var logFlags = obj.logFlags;
                if (logFlags !== undefined) {
                    currentFlags = logFlags.value;
                    for (var i = 0; i < numTraceFlags; i++) {
                        traceFlags[i].setForceValue(logFlags.force);
                    }
                    that.onflagschanged.notify();
                    if (currentFlags != 0) traceMask.container.innerText = "Trace Mask: 0x" + currentFlags.replace(/^0+/, '');
                    else traceMask.container.innerText = "";
                }     
                var disableDmpFiles = obj.disableDmpFiles;
                if (disableDmpFiles !== undefined) {
                    dmpActive = disableDmpFiles.value;
                    dmpCheckbox.container.style.backgroundColor = dmpActive ? "var(--check-bg)" : "var(--uncheck-bg)";
                    dmpCheckbox.container.style.fill = dmpActive ? "var(--check-c)" : "var(--uncheck-bg)";
                }   
            }
            else if (obj.mt == "EMailLogAvailable") {
                emailLog.container.style.display = "inline-flex";
            }
        });

        function TraceFlag(owner, name, mask) {
            var that = this,
                force = false,
                checkbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
                title = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); font-size: 14px; line-height: 20px; margin: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;", name);

            this.createNode("button", "flex: 1 1 150px; margin: 4px; padding: 0; text-align: left; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; border-radius: 5px; overflow: hidden;");
            this.add(checkbox);
            this.add(title);
            this.container.addEventListener("click", function () {
                if (force === false) owner.toggleFlag(mask);
            });
            owner.onflagschanged.attach(update);
            update();

            this.setForceValue = function (forceTf) {
                force = forceTf;
                checkbox.container.disabled = force !== false;
                this.container.style.opacity = force ? "0.5" : null;
            }

            function update() {
                var active = (("0000000" + Number((parseInt(currentFlags.substring( 0, 8),16) & parseInt(mask.substring( 0, 8),16)) >>> 0).toString(16)).substr(-8) +
                              ("0000000" + Number((parseInt(currentFlags.substring( 8,16),16) & parseInt(mask.substring( 8,16),16)) >>> 0).toString(16)).substr(-8)) != "0000000000000000";
                checkbox.container.style.backgroundColor = active ? "var(--check-bg)" : "var(--uncheck-bg)";
                checkbox.container.style.fill = active ? "var(--check-c)" : "var(--uncheck-bg)";
            }
        }
        TraceFlag.prototype = innovaphone.ui1.nodePrototype;
    }
    PageTrace.prototype = innovaphone.ui1.nodePrototype;

    function ExternalApp(owner, parentObj, childId, id, name, path, param, autostart, lang, editExternalApp, editedExternalApp, delExternalApp) {
        var that = this,

            mainDiv = new innovaphone.ui1.Node("div", "font-size: 14px; width:100%; position:relative; display:flex; flex-direction:row; flex-wrap: wrap; align-items: center; margin:5px; background-color: var(--line2px); order:0;"),

            extAppsIconSvgDiv = new innovaphone.ui1.Node("div", "flex:0 0 auto; width: 30px; height: 30px; margin: 5px; padding: 0; display: flex; align-items: center; justify-content: center; fill:var(--icon-bg);"),
            extAppsIconSvg = new innovaphone.ui1.SvgInline("height:20px; width:20px; fill:(--radio-border); pointer-events: none;", icons.externalapps.viewbox, icons.externalapps.code),
            divTextMainDiv = new innovaphone.ui1.Node("div", "flex:1 1 auto; display: flex; fill:var(--icon-bg);"),
            textMainDiv = new innovaphone.ui1.Node("div", "font-size: 14px; position:relative; display:flex; flex-direction:row; flex-wrap: wrap; width:100%; background-color: var(--line2px);"),
            nameDivMain = new innovaphone.ui1.Node("div", "position:relative; flex: 0 1 auto; display:flex; flex-direction:row;"),
            nameDivText = new innovaphone.ui1.Node("div", "position:relative; flex: 0 1 auto; margin-right: 10px; background-color:transparent;color:var(--c1);", name);
            pathDivMain = new innovaphone.ui1.Node("div", "position:relative; flex: 0 1 auto; display:flex; flex-direction:row;"),
            pathDivText = new innovaphone.ui1.Node("div", "position:relative; flex: 0 1 auto; margin-right: 10px; background-color:transparent;color:var(--c1); overflow: hidden", path),
            paramDivMain = new innovaphone.ui1.Node("div", "position:relative; flex: 0 1 auto; display:flex; flex-direction:row;"),
            paramDivText = new innovaphone.ui1.Node("div", "position:relative; flex: 0 0 auto; min-width: 32px; margin-right: 10px; background-color:transparent;color:var(--c1); overflow: hidden", param),
            autostartDivMain = new innovaphone.ui1.Node("div", "position:relative; flex: 0 1 auto; display:flex; flex-direction:row;"),
            autostartDivText = new innovaphone.ui1.Node("div", "position:relative; flex: 0 0 auto; min-width: 32px; margin-right: 10px; background-color:transparent;color:var(--c1); overflow: hidden", "Autostart").addTranslation(lang, "autostart"),
            extAppsIconsDiv = new innovaphone.ui1.Node("div", "position: relative;flex:0 0 auto; display: flex; cursor:pointer; fill:var(--icon-bg);"),
            inlineButtonStyle = "flex:0 0 auto; width: 30px; height: 30px; margin: 5px; padding: 0; background: transparent; display: flex; align-items: center; justify-content: center; cursor:pointer; fill:var(--icon-bg);",
            extAppsIconEditSvgDiv = new innovaphone.ui1.Node("button", inlineButtonStyle),
            extAppsIconEditSvg = new innovaphone.ui1.SvgInline("height:20px; width:20px; fill:(--radio-border); pointer-events:none;", icons.edit.viewbox, icons.edit.code),
            extAppsIconCheckSvgDiv = new innovaphone.ui1.Node("button", inlineButtonStyle + "display:none;"),
            extAppsIconCheckSvg = new innovaphone.ui1.SvgInline("height:20px; width:20px; fill:(--radio-border); pointer-events:none;", icons.check.viewbox, icons.check.code),
            extAppsIconDelSvgDiv = new innovaphone.ui1.Node("button", inlineButtonStyle),
            extAppsIconDelSvg = new innovaphone.ui1.SvgInline("height:20px; width:20px; fill:(--radio-border); pointer-events:none;", icons.del.viewbox, icons.del.code);

        this.createNode("div", "position:relative; width:100%; max-width:1200px; display:flex; flex-direction:row; flex-wrap: wrap; margin-bottom: 2px; background-color: var(--line2px); order:0; border-radius: var(--border-radius);");

        extAppsIconSvgDiv.add(extAppsIconSvg);
        mainDiv.add(extAppsIconSvgDiv);

        nameDivMain.add(nameDivText);
        pathDivMain.add(pathDivText);
        paramDivMain.add(paramDivText);
        autostartDivMain.add(autostartDivText);

        textMainDiv.add(nameDivMain);
        textMainDiv.add(pathDivMain);
        textMainDiv.add(paramDivMain);
        if (autostart) textMainDiv.add(autostartDivMain);
        divTextMainDiv.add(textMainDiv);
        mainDiv.add(divTextMainDiv);

        extAppsIconEditSvgDiv.testId("editExternalApp-" + name);
        extAppsIconDelSvgDiv.testId("delExternalApp-" + name);

        extAppsIconEditSvgDiv.add(extAppsIconEditSvg);
        extAppsIconEditSvgDiv.container.addEventListener("click", editApp);
        extAppsIconEditSvgDiv.container.setAttribute("index", childId);

        extAppsIconCheckSvgDiv.add(extAppsIconCheckSvg);
        extAppsIconCheckSvgDiv.container.addEventListener("click", editedApp);
        extAppsIconCheckSvgDiv.container.setAttribute("index", childId);

        extAppsIconDelSvgDiv.add(extAppsIconDelSvg);
        extAppsIconDelSvgDiv.container.addEventListener("click", deleteApp);
        extAppsIconDelSvgDiv.container.setAttribute("index", childId);

        extAppsIconsDiv.add(extAppsIconEditSvgDiv);
        extAppsIconsDiv.add(extAppsIconCheckSvgDiv);
        extAppsIconsDiv.add(extAppsIconDelSvgDiv);
        mainDiv.add(extAppsIconsDiv);

        this.add(mainDiv);

        function editApp(event) {
            var index = event.currentTarget.getAttribute("index");
            var cont = parentObj.container.childNodes[index];
            console.log('editApp ' + id + ' ind=' + index);
            editExternalApp(id, name, path, param, autostart);
            cont.childNodes[0].childNodes[2].childNodes[0].style.display = "none";
            cont.childNodes[0].childNodes[2].childNodes[1].style.display = "flex";
        }

        function editedApp(event) {
            if (owner.checkNamePath() == 1) {
                var index = event.currentTarget.getAttribute("index");
                var cont = parentObj.container.childNodes[index];

                console.log('editedApp ' + id + ' ind=' + index);

                cont.childNodes[0].childNodes[2].childNodes[0].style.display = "flex";
                cont.childNodes[0].childNodes[2].childNodes[0].style.display = "none";
                editedExternalApp(id);
            }
        }

        function deleteApp(event) {
            var index = event.currentTarget.getAttribute("index");
            var cont = parentObj.container.childNodes[index];

            console.log('deleteApp ' + id + ' name=' + name + ' ind=' + index);
            delExternalApp(id);
        }
    }
    ExternalApp.prototype = innovaphone.ui1.nodePrototype;

    function PageHotkeys(owner, lang, send) {
        var that = this,
            hotkeys = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-left: 10px; margin-top: 10px; padding: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "hotkeys"),
            hotkeysInfo = new innovaphone.ui1.Node("div", "margin-left: 10px; display: inline-flex; align-items: start; gap: 5px;"),
            hotkeysInfoIcon = new innovaphone.ui1.SvgInline("flex: 0 0 auto;width: 20px;height:20px;fill: var(--c2);pointer-events: none;", icons.info.viewbox, icons.info.code),
            hotkeysInfoText = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c2);").addTranslation(lang, "hotkeysInfo"),
            hotkeysInfoMacOs = new innovaphone.ui1.Node("div", "left: 15px; margin-left: 10px; display: inline-flex; align-items: center;"),
            hotkeysInfoTextMacOs = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c2); padding-left: 15px; padding-top: 2px;").addTranslation(lang, "hotkeysInfoMacOs"),
            hotkeyDial = new PageHotkeys.Hotkey(that, lang, "hotkeyDial"),
            hotkeyAccept = new PageHotkeys.Hotkey(that, lang, "hotkeyAccept"),
            hotkeyReject = new PageHotkeys.Hotkey(that, lang, "hotkeyReject"),
            hotkeyAppLink0 = new PageHotkeys.Hotkey(that, lang, "hotkeyAppLink0", true, "hotkeyAppLink"),
            hotkeyAppLink1 = new PageHotkeys.Hotkey(that, lang, "hotkeyAppLink1", true, "hotkeyAppLink"),
            hotkeyAppLink2 = new PageHotkeys.Hotkey(that, lang, "hotkeyAppLink2", true, "hotkeyAppLink");

        this.checkOtherHotkeys = function (type, hotkey) {
            var t0 = hotkeyDial.getHotkeyValue();
            var t1 = hotkeyAccept.getHotkeyValue();
            var t2 = hotkeyReject.getHotkeyValue();
            var t3 = hotkeyAppLink0.getHotkeyValue();
            var t4 = hotkeyAppLink1.getHotkeyValue();
            var t5 = hotkeyAppLink2.getHotkeyValue();
            var error = 0;
            var t = 0;
            if (type == "hotkeyDial" && hotkey != t1 && hotkey != t2 && hotkey != t3 && hotkey != t4 && hotkey != t5) {
                console.log("Hotkey for hotkeyDial not set " + t1 + ", " + t2 + ", " + t3 + ", " + t4 + ", " + t5 + "  != " + hotkey);
                return 1;
            }
            else if (type == "hotkeyAccept" && hotkey != t0 && hotkey != t2 && hotkey != t3 && hotkey != t4 && hotkey != t5) {
                console.log("Hotkey for hotkeyAccept not set " + t0 + ", " + t2 + ", " + t3 + ", " + t4 + ", " + t5 + "  != " + hotkey);
                return 1;
            }
            else if (type == "hotkeyReject" && hotkey != t0 && hotkey != t1 && hotkey != t3 && hotkey != t4 && hotkey != t5) {
                console.log("Hotkey for hotkeyReject not set " + t0 + ", " + t1 + ", " + t3 + ", " + t4 + ", " + t5 + "  != " + hotkey);
                return 1;
            }
            else if (type == "hotkeyAppLink0" && hotkey != t0 && hotkey != t1 && hotkey != t2 && hotkey != t4 && hotkey != t5) {
                console.log("Hotkey for hotkeyAppLink0 not set " + t0 + ", " + t1 + ", " + t2 + ", " + t4 + ", " + t5 + "  != " + hotkey);
                t = hotkeyAppLink0.getHotkeyAppLink();
                if (t == null || t == "") error = 1;
                else return 1;
            }
            else if (type == "hotkeyAppLink1" && hotkey != t0 && hotkey != t1 && hotkey != t2 && hotkey != t3 && hotkey != t5) {
                console.log("Hotkey for hotkeyAppLink1 not set " + t0 + ", " + t1 + ", " + t2 + ", " + t3 + ", " + t5 + "  != " + hotkey);
                t = hotkeyAppLink1.getHotkeyAppLink();
                if (t == null || t == "") error = 1;
                else return 1;
            }
            else if (type == "hotkeyAppLink2" && hotkey != t0 && hotkey != t1 && hotkey != t2 && hotkey != t3 && hotkey != t4) {
                console.log("Hotkey for hotkeyAppLink2 not set " + t0 + ", " + t1 + ", " + t2 + ", " + t3 + ", " + t4 + "  != " + hotkey);
                t = hotkeyAppLink2.getHotkeyAppLink();
                if (t == null || t == "") error = 1;
                else return 1;
            }
            console.log("Hotkey for " + type + " already set " + t0 + ", " + t1 + ", " + t2 + ", " + t3 + ", " + t4 + ", " + t5 + ", " + t + " != " + hotkey);
            if (type == "hotkeyDial") {
                hotkeyDial.clearError();
                hotkeyDial.setError("errorHotkeyDefined");
            }
            else if (type == "hotkeyAccept") {
                hotkeyAccept.clearError();
                hotkeyAccept.setError("errorHotkeyDefined");
            }
            else if (type == "hotkeyReject") {
                hotkeyReject.clearError();
                hotkeyReject.setError("errorHotkeyDefined");
            }
            else if (type == "hotkeyAppLink0") {
                hotkeyAppLink0.clearError();
                if (error == 0) hotkeyAppLink0.setError("errorHotkeyDefined");
                else hotkeyAppLink0.setError("errorHotkeyAppLinkEmpty");
            }
            else if (type == "hotkeyAppLink1") {
                hotkeyAppLink1.clearError();
                if (error == 0) hotkeyAppLink1.setError("errorHotkeyDefined");
                else hotkeyAppLink1.setError("errorHotkeyAppLinkEmpty");
            }
            else {
                hotkeyAppLink2.clearError();
                if (error == 0) hotkeyAppLink2.setError("errorHotkeyDefined");
                else hotkeyAppLink2.setError("errorHotkeyAppLinkEmpty");
            }
            return 0;
        }

        this.sendHotkey = function (hotkey) {
            send(hotkey);
        };

        this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; padding: 5px; overflow: auto;");
        this.add(hotkeys);
        hotkeysInfo.add(hotkeysInfoIcon);
        hotkeysInfo.add(hotkeysInfoText);
        this.add(hotkeysInfo);
        if (navigator.platform.indexOf("MacIntel") != -1) {
            hotkeysInfoMacOs.add(hotkeysInfoTextMacOs);
            this.add(hotkeysInfoMacOs);
        }
        this.add(hotkeyDial);
        this.add(hotkeyAccept);
        this.add(hotkeyReject);
        this.add(hotkeyAppLink0);
        this.add(hotkeyAppLink1);
        this.add(hotkeyAppLink2);

        owner.onmessage.attach(function (sender, obj) {
            if (obj.mt == "ClientConfig") {
                if (obj.hotkeyDial !== undefined) {
                    var hd = obj.hotkeyDial;
                    hotkeyDial.initHotkey(hd.value, hd.force);
                }
                if (obj.hotkeyAccept !== undefined) {
                    var ha = obj.hotkeyAccept;
                    hotkeyAccept.initHotkey(ha.value, ha.force);
                }
                if (obj.hotkeyReject !== undefined) {
                    var hr = obj.hotkeyReject;
                    hotkeyReject.initHotkey(hr.value, hr.force);
                }
                if (obj.hotkeyAppLink0 !== undefined) {
                    var hr = obj.hotkeyAppLink0;
                    hotkeyAppLink0.initHotkey(hr.value, hr.force, hr.appLink);
                }
                if (obj.hotkeyAppLink1 !== undefined) {
                    var hr = obj.hotkeyAppLink1;
                    hotkeyAppLink1.initHotkey(hr.value, hr.force, hr.appLink);
                }
                if (obj.hotkeyAppLink2 !== undefined) {
                    var hr = obj.hotkeyAppLink2;
                    hotkeyAppLink2.initHotkey(hr.value, hr.force, hr.appLink);
                }
            }
        });
    }
    PageHotkeys.prototype = innovaphone.ui1.nodePrototype;

    function PageExternalApps(owner, lang, send) {
        var that = this,
            appId = 0,
            inputStyle = "margin-left: 15px; margin-top: 5px; padding-left: 10px;height: 32px; border-radius: 16px; box-sizing:border-box; border: 0em; width:100%; background-color: var(--search-bg); color: var(--c2); text-overflow: ellipsis",
            title = new innovaphone.ui1.Node("div", "font-size: 16px; color: var(--c1); margin-left: 10px; margin-top:10px; padding: 5px;").addTranslation(lang, "externalapps"),
            extAppsInfo = new innovaphone.ui1.Node("div", "margin-left: 10px; display: inline-flex; align-items: start; gap: 5px;"),
            extAppsInfoIconSvg = new innovaphone.ui1.SvgInline("flex: 0 0 auto;width: 20px;height:20px;fill: var(--c2);pointer-events: none;", icons.info.viewbox, icons.info.code),
            extAppsInfoText = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c2);").addTranslation(lang, "extAppsInfo"),
            extAppNew = new innovaphone.ui1.Node("div", "position:relative; left: 5px; margin-left: 10px; margin-top:15px; margin-right: 15px; max-width: 925px; background-color: var(--tabs-bg); border-radius: var(--border-radius); overflow: hidden;"),
            extAppsAddInfo = new innovaphone.ui1.Node("div", "display:flex; flex-direction:row; align-items:start; flex-wrap:nowrap; flex:0 0 auto; overflow:hidden; color:var(--c1);"),
            extAppsAddInfoText = new innovaphone.ui1.Node("div", "display:flex; flex-direction:row; padding:15px 10px 10px 25px; flex-wrap:nowrap; flex:1 1 auto; overflow:hidden;").addTranslation(lang, "addExtApp"),
            extAppsAddInfoIcon = new innovaphone.ui1.Node("button", "flex:0 0 auto; margin:5px; padding:5px; background-color:var(--bg3); fill:var(--c1); align-items:center; justify-content:center; border-radius:50%; outline-offset:-2px; cursor:pointer;"),
            extAppsAddInfoIconSvg = new innovaphone.ui1.SvgInline("height:20px; width:20px; pointer-events: none;", icons.help.viewbox, icons.help.code),
            extAppsAddInfoText1 = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c2); margin-left: 10px; padding-left: 15px; padding-top: 5px; margin-right: 15px;").addTranslation(lang, "addExtAppInfo"),
            inputContainer = new innovaphone.ui1.Div("position:relative; max-width: 500px; padding-left: 10px; padding-top: 10px; padding-right: 20px;"),
            inputNameText = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c1); margin-left: 10px; padding-left: 15px; margin-top: 15px;").addTranslation(lang, "addExtAppNameText"),
            inputNameDiv = new innovaphone.ui1.Node("div", "position:relative; max-width: 500px;margin-right:15px;"),
            inputName = new innovaphone.ui1.Input(inputStyle).addTranslation(lang, "addExtAppName", "placeholder"),
            inputNameError = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--red); margin-left: 10px; padding-bottom: 10px; padding-left: 5px; padding-top: 5px;").addTranslation(lang, "inputNameError"),
            inputPathText = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c1); margin-left: 10px; padding-left: 15px;margin-top: 15px;").addTranslation(lang, "addExtAppPfadText"),
            inputPath = null, //new innovaphone.ui1.Input("margin-left: 15px; margin-top: 5px; padding-left: 10px;height: 32px; box-sizing:border-box; border: 0em; width:100%; background-color: var(--search-bg); color: var(--c2); text-overflow: ellipsis;").addTranslation(lang, "addExtAppPfad", "placeholder"),
            inputPathDiv = new innovaphone.ui1.Node("div", "position:relative; max-width: 500px;margin-right:15px;"),
            inputParamText = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c1); margin-left: 10px; padding-left: 15px;margin-top: 15px;").addTranslation(lang, "addExtAppParamText"),
            inputParam = new innovaphone.ui1.Input(inputStyle).addTranslation(lang, "addExtAppParam", "placeholder"),
            inputParamDiv = new innovaphone.ui1.Node("div", "position:relative; max-width: 500px;margin-right:15px;"),
            extAutostartCheckbox = new innovaphone.ui1.SvgInline(checkBoxStyle, icons.checkmark.viewbox, icons.checkmark.code),
            extAutostartTitle = new innovaphone.ui1.Node("div", "flex: 1 1 0; color: var(--c1); margin: 0 8px 0 4px; font-size: 14px; line-height: 20px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, "autostart"),
            extAutostartDiv = new innovaphone.ui1.Node("button", "flex: 1 1 150px; margin: 15px 15px 10px 15px; padding: 0; text-align: left; display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; border-radius: 5px; overflow: hidden;"),
            extAutostartActive = 0,
            editExternalAppId = -1,
            buttonStyle = "left: 5px; font-size: 14px; margin-left: 25px; margin-top: 5px; margin-bottom: 20px; height: 34px; padding-left: 10px; padding-right: 10px; display: inline-flex; align-items: center; justify-content:center; color: var(--c1); background-color: var(--button); border-radius: var(--border-radius)",
            saveButtonDiv = new innovaphone.ui1.Node("button", buttonStyle, null, "button").addTranslation(lang, "extAppsSaveButton"),
            addButtonDiv = new innovaphone.ui1.Node("button", buttonStyle, null, "button").addTranslation(lang, "extAppsAddButton"),
            extAppsHelp = new innovaphone.ui1.Node("div", "position: absolute; top: 10px; right: 10px; width: calc(100% - 20px);width: calc(100% - 20px);max-width: 460px; padding: 15px 20px; box-sizing: border-box; border: 1px solid var(--yellow); border-radius: var(--border-radius); background-color: var(--hotkey-bg); box-shadow: 0 0 10px var(--button); z-index: 10;"),
            extAppsHelpDiv = new innovaphone.ui1.Node("div", "display:flex; flex-direction:row; flex-wrap:nowrap; flex:0 0 auto; overflow:hidden;"),
            extAppsHelpBtn = new innovaphone.ui1.Node("button", "position: absolute; top:5px; right:5px; align-items:center; justify-content:center; padding:5px; background:transparent !important; fill:var(--c1); cursor:pointer;"),
            extAppsHelpBtnSvg = new innovaphone.ui1.SvgInline("height:20px; width:20px; pointer-events:none;", icons.close.viewbox, icons.close.code),
            extAppsHelpText = new innovaphone.ui1.Node("div", "display:flex; flex-direction:row; flex-wrap:nowrap; flex:1 1 auto; margin-bottom:10px; overflow:hidden; font-size:16px; color:var(--c2);").addTranslation(lang, "extAppsHelp"),
            extAppsHelpTextn = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c2); padding-top: 3px;").addTranslation(lang, "extAppsHelpn"),
            extAppsHelpTextN = new innovaphone.ui1.Node("div", "font-size: 14px; margin-top: 5px; color: var(--c1); padding-top: 3px;").addTranslation(lang, "extAppsHelpNat"),
            extAppsHelpTextI = new innovaphone.ui1.Node("div", "font-size: 14px; margin-top: 5px; color: var(--c1); padding-top: 3px;").addTranslation(lang, "extAppsHelpI"),
            extAppsHelpTextu = new innovaphone.ui1.Node("div", "font-size: 14px; margin-top: 5px; color: var(--c1); padding-top: 3px;").addTranslation(lang, "extAppsHelpu"),
            extAppsHelpTextd = new innovaphone.ui1.Node("div", "font-size: 14px; margin-top: 5px; color: var(--c1); padding-top: 3px;").addTranslation(lang, "extAppsHelpd"),
            extAppsHelpTextc = new innovaphone.ui1.Node("div", "font-size: 14px; margin-top: 5px; color: var(--c1); padding-top: 3px;").addTranslation(lang, "extAppsHelpc"),
            externalAppsTitle = new innovaphone.ui1.Node("div", "font-size: 14px; color: var(--c1); margin-left: 15px; margin-top:20px; margin-bottom: 10px; display: none;").addTranslation(lang, "extApps"),
            externalApps0 = new innovaphone.ui1.Node("div", "position: relative; margin-left: 15px; order: 4; flex: 1 1 0px; overflow: hidden auto;"),
            externalApps1 = new innovaphone.ui1.Node("div", "box-sizing: border-box;"),
            externalApps2 = new innovaphone.ui1.Node("div", "position:relative; order:0; display: flex; flex-direction: row; flex-wrap: wrap;");

        if(navigator.platform.indexOf("MacIntel") != -1) {
            inputPath = new innovaphone.ui1.Input(inputStyle).addTranslation(lang, "addExtAppPfadMacOs", "placeholder");     
        }
        else {
            inputPath = new innovaphone.ui1.Input(inputStyle).addTranslation(lang, "addExtAppPfad", "placeholder");
        }
        this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; padding: 5px; overflow: auto;");
        this.add(title);
        extAppsInfo.add(extAppsInfoIconSvg);
        extAppsInfo.add(extAppsInfoText);
        this.add(extAppsInfo);

        // Help Div
        extAppsHelpDiv.add(extAppsHelpText);
        extAppsHelpDiv.add(extAppsHelpBtn);
        extAppsHelpBtn.addEvent("click", hideHelpMenu);
        extAppsHelpBtn.add(extAppsHelpBtnSvg);
        extAppsHelp.add(extAppsHelpDiv);
        extAppsHelp.add(extAppsHelpTextn);
        extAppsHelp.add(extAppsHelpTextN);
        extAppsHelp.add(extAppsHelpTextI);
        extAppsHelp.add(extAppsHelpTextu);
        extAppsHelp.add(extAppsHelpTextd);
        extAppsHelp.add(extAppsHelpTextc);

        extAppsHelp.container.style.display = "none";

        extAppNew.add(extAppsHelp);

        inputName.testId("externalAppName");
        inputPath.testId("externalAppPath");
        inputParam.testId("externalAppParam");
        extAutostartCheckbox.testId("autostartExternalApp");
        addButtonDiv.testId("addExternalApp");
        saveButtonDiv.testId("saveExternalApp");

        // Add Div
        extAppsAddInfo.add(extAppsAddInfoText);
        extAppsAddInfoIcon.addEvent("click", showHelpMenu);
        extAppsAddInfoIcon.add(extAppsAddInfoIconSvg);
        extAppsAddInfo.add(extAppsAddInfoIcon);
        extAppNew.add(extAppsAddInfo);
        extAppNew.add(extAppsAddInfoText1);
        inputContainer.add(inputNameText);
        inputNameDiv.add(inputName);
        inputContainer.add(inputNameDiv);

        inputContainer.add(inputPathText);
        inputPathDiv.add(inputPath);
        inputContainer.add(inputPathDiv);

        inputContainer.add(inputParamText);
        inputParamDiv.add(inputParam);
        inputContainer.add(inputParamDiv);

        extAutostartDiv.add(extAutostartCheckbox);
        extAutostartDiv.add(extAutostartTitle);
        extAutostartDiv.addEvent("click", function (e) {
            extAutostartActive = !extAutostartActive;
            extAutostartCheckbox.container.style.backgroundColor = extAutostartActive ? "var(--check-bg)" : "var(--uncheck-bg)";
            extAutostartCheckbox.container.style.fill = extAutostartActive ? "var(--check-c)" : "var(--uncheck-bg)";
        });
        inputContainer.add(extAutostartDiv);

        extAppNew.add(inputContainer);
        addButtonDiv.addEvent("click", addExternalApp);
        extAppNew.add(addButtonDiv);

        saveButtonDiv.addEvent("click", saveExternalApp);

        this.add(extAppNew);
        this.add(externalAppsTitle);

        externalApps1.add(externalApps2);
        externalApps0.add(externalApps1);
        this.add(externalApps0);

        function showHelpMenu() {
            console.log('showHelpMenu');
            extAppsHelp.container.style.display = "block";
            setTimeout(() => extAppsHelpBtn.container.focus());
        }

        function hideHelpMenu() {
            console.log('hideHelpMenu');
            extAppsHelp.container.style.display = "none";
        }

        function addExternalApp() {
            console.log('addExternalApp name=' + inputName.getValue(true) + ' path=' + inputPath.getValue(true) + ' param=' + inputParam.getValue(true) + ' autostart=' + extAutostartActive);
            if (inputName.getValue(true) == "" || inputPath.getValue(true) == "") {
                inputContainer.add(inputNameError);
                if (extAutostartActive) {
                    extAutostartCheckbox.container.style.backgroundColor = "var(--uncheck-bg)";
                    extAutostartCheckbox.container.style.fill = "var(--uncheck-bg)";
                    extAutostartActive = false;
                }
            }
            else {
                send({ mt: "ClientConfig", externalAppId: appId, externalAppName: inputName.getValue(true), externalAppPath: inputPath.getValue(true), externalAppParam: inputParam.getValue(true), externalAutostartApp: extAutostartActive });
                appId = appId + 1;
                inputContainer.rem(inputNameError);
                if (extAutostartActive) {
                    extAutostartCheckbox.container.style.backgroundColor = "var(--uncheck-bg)";
                    extAutostartCheckbox.container.style.fill = "var(--uncheck-bg)";
                    extAutostartActive = false;
                }
            }
        }

        function editExternalApp(id, name, path, param, autostart) {
            if(name != null) inputName.container.style.color = "var(--c1)";
            inputName.container.value = name;
            if(path != null) inputPath.container.style.color = "var(--c1)";
            inputPath.container.value = path;
            if(param != null) inputParam.container.style.color = "var(--c1)";
            inputParam.container.value = param;
            extAutostartCheckbox.container.style.backgroundColor = autostart ? "var(--check-bg)" : "var(--uncheck-bg)";
            extAutostartCheckbox.container.style.fill = autostart ? "var(--check-c)" : "var(--uncheck-bg)";
            extAutostartActive = autostart;
            extAppNew.rem(addButtonDiv);
            extAppNew.add(saveButtonDiv);
            editExternalAppId = id;
        }

        function saveExternalApp() {
            if (editExternalAppId != -1) {
                send({ mt: "ClientConfig", externalAppId: editExternalAppId, externalAppName: inputName.getValue(true), externalAppPath: inputPath.getValue(true), externalAppParam: inputParam.getValue(true), externalAutostartApp: extAutostartActive });
                inputName.container.style.color = "var(--c2)";
                inputName.container.value = "";
                inputPath.container.style.color = "var(--c2)";
                inputPath.container.value = "";
                inputParam.container.style.color = "var(--c2)";
                inputParam.container.value = "";
                extAutostartCheckbox.container.style.backgroundColor = "var(--uncheck-bg)";
                extAutostartCheckbox.container.style.fill = "var(--uncheck-bg)";
                extAutostartActive = false;
                extAppNew.add(addButtonDiv);
                extAppNew.rem(saveButtonDiv);
                editExternalAppId = -1;
            }
        }

        function editedExternalApp(id) {
            send({ mt: "ClientConfig", externalAppId: id, externalAppName: inputName.getValue(true), externalAppPath: inputPath.getValue(true), externalAppParam: inputParam.getValue(true), externalAutostartApp: extAutostartActive });
            inputName.container.style.color = "var(--c2)";
            inputName.container.value = "";
            inputPath.container.style.color = "var(--c2)";
            inputPath.container.value = "";
            inputParam.container.style.color = "var(--c2)";
            inputParam.container.value = "";
            extAutostartCheckbox.container.style.backgroundColor = "var(--uncheck-bg)";
            extAutostartCheckbox.container.style.fill = "var(--uncheck-bg)";
            extAutostartActive = false;
            extAppNew.add(addButtonDiv);
            extAppNew.rem(saveButtonDiv);
            editExternalAppId = -1;
        }

        function delExternalApp(id) {
            send({ mt: "ClientConfig", externalAppId: id });
            inputContainer.rem(inputNameError);
            extAppNew.add(addButtonDiv);
            extAppNew.rem(saveButtonDiv);
            editExternalAppId = -1;
        }

        this.checkNamePath = function () {
            if (inputName.getValue(true) == "" || inputPath.getValue(true) == "") {
                inputContainer.add(inputNameError);
                return 0;
            }
            inputContainer.rem(inputNameError);
            return 1;
        }

        owner.onmessage.attach(function (sender, obj) {
            if (obj.mt == "ClientConfig") {
                externalApps2.container.innerHTML = "";
                externalApps1.rem(externalApps2);

                var apps = obj.externalApps;
                if (apps) {
                    externalAppsTitle.container.style.display = "block";
                    obj.externalApps.forEach(function (e) {
                        externalApps2.add(new ExternalApp(that, externalApps2, externalApps2.container.childNodes.length, e.id, e.name, e.path, e.param, e.autostart, lang, editExternalApp, editedExternalApp, delExternalApp));
                        if (e.id >= appId) appId = e.id + 1;
                    });
                }
                else {
                    externalAppsTitle.container.style.display = "none";
                }
                inputName.container.value = "";
                inputPath.container.value = "";
                inputParam.container.value = "";
                externalApps1.add(externalApps2);
            }
        });
    }
    PageExternalApps.prototype = innovaphone.ui1.nodePrototype;

    function Tabs(lang) {
        var that = this,
            nav = new innovaphone.ui1.Node("nav", "margin-left: 1px; flex: 0 0 auto; background-color: var(--tabs-bg);", null, "tabs"),
            main = new innovaphone.ui1.Node("main", "flex: 1 1 0; background-color: var(--content-bg); position: relative;"),
            activeTab = null;

        this.onactivate = new innovaphone.lib1.Event(this);
        this.createNode("body", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; display: flex; flex-direction: row; margin: 0px; padding: 0px; background-color: var(--main-bg); -webkit-overflow-scrolling: touch; -moz-overflow-scrolling: touch; overflow-scrolling: touch;");
        this.container.style.setProperty("--border-radius", "10px");
        this.add(main);
        this.add(nav);

        this.add = function (textId, icon, content) {
            var tab = new Tab(that, lang, textId, icon, content);
            nav.add(tab);
            if (content) main.add(content);
            that.onactivate.notify(activeTab);
            return tab;
        }

        this.setActive = function (tab) {
            activeTab = tab;
            that.onactivate.notify(activeTab);
        }

        function Tab(tabs, lang, textId, icon, content) {
            var that = this;

            this.createNode("button", "margin:0; padding:0; width:100%; text-align:left; justify-content:normal; background-color:var(--highlight-bg); color:var(--c1); fill:var(--c1); outline-offset:-2px;");
            this.add(new innovaphone.ui1.SvgInline("flex:0 0 auto; padding:13px; height:50px; width:50px; box-sizing:border-box; fill:var(--c2); pointer-events:none;", icon.viewbox, icon.code, null));
            this.add(new innovaphone.ui1.Node("div", "flex: 1 1 auto; margin-right: 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;").addTranslation(lang, textId));
            this.addTranslation(lang, textId, "title");
            this.setActive = function () {
                tabs.setActive(that);
            };
            this.container.addEventListener("click", function () {
                tabs.setActive(that);
            });
            tabs.onactivate.attach(function (sender, obj) {
                that.container.style.backgroundColor = obj == that ? "var(--highlight-bg)" : "transparent";
                if (content) content.container.style.display = obj == that ? "block" : "none";
            });
        }
        Tab.prototype = innovaphone.ui1.nodePrototype;
    }
    Tabs.prototype = innovaphone.ui1.nodePrototype;

    function App(start) {
        var that = this,
            lang = new innovaphone.lib1.Languages(innovaphone.pbx.appclient.start.lang, (navigator.language || "en").split("-")[0].toLowerCase()),
            schemes = new innovaphone.ui1.CssVariables(schemeDefinitions),
            connection = new innovaphone.appwebsocket.Connection(start.url, start.name || "client"),
            tabs = new Tabs(lang);

        this.onmessage = new innovaphone.lib1.Event(this);

        if (navigator.userAgent.indexOf("IP270") != -1) tabs.add("settings", icons.settings, new PageIP270Settings(that, lang, connection.send)).setActive();
        else if (navigator.platform.indexOf("Win") != -1 || navigator.platform.indexOf("MacIntel") != -1 || (navigator.platform.indexOf("Linux") != -1 && navigator.userAgent.indexOf("Android") == -1)) {
            tabs.add("settings", icons.settings, new PageSettings(that, lang, connection.send)).setActive();
            tabs.add("hotkeys", icons.hotkey, new PageHotkeys(that, lang, connection.send));
            tabs.add("externalapps", icons.externalapps, new PageExternalApps(that, lang, connection.send));
        }
        else if (navigator.platform.indexOf("Android") != -1 || navigator.platform.indexOf("Linux") != -1) tabs.add("settings", icons.settings, new PageAndroidSettings(that, lang, connection.send)).setActive();
        else if (navigator.platform.indexOf("iPhone") != -1 || navigator.platform.indexOf("iPad") != -1) tabs.add("settings", icons.settings, new PageIOSSettings(that, lang, connection.send)).setActive();
        tabs.add("trace", icons.trace, new PageTrace(that, lang, connection.send));
        
        start.onschemechanged.attach(function () { schemes.activate(start.scheme); });
        start.onlangchanged.attach(function () { lang.activate(start.lang); });
        schemes.activate(start.scheme);
        lang.activate(start.lang);

        connection.onconnected = function (domain, user, dn) { };
        connection.onmessage = function (msg) {
            if (msg) that.onmessage.notify(msg);
        };
        connection.onclosed = function () { };
        connection.onerror = function (error) { };
    }

    return new App(start);
};
