var innovaphone = innovaphone || {};
innovaphone.pbx = innovaphone.pbx || {};
innovaphone.pbx.appclient = innovaphone.pbx.appclient || {};
var icons = {
    trace: { viewbox: '0 0 24 24', 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 24 24', 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 24 24', 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 16 16', 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 32 32', 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>' },
    call: { viewbox: '0 0 24 24', code: '<path d="M9.21,0A.35.35,0,0,0,8.8.2,27.38,27.38,0,0,0,7,6.5c0,.44,2.08,11.08,2.75,13.23a.41.41,0,0,0,.48.26c.49-.1,1.69-.4,2.33-.56a.55.55,0,0,0,.43-.5c0-.82-.12-3.87-.18-4.87a.42.42,0,0,0-.35-.42,5.62,5.62,0,0,1-2.58-1s-1.27-5.34-1-5.69c.43-.5,2.54-1,2.87-1.31.12-.1.28-3.33.44-4.18a.35.35,0,0,0-.17-.38A14.59,14.59,0,0,0,9.21,0Z">' },
    close: { viewbox: '0 0 32 32', 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"/>' },
    blocked: { viewbox: '0 0 24 24', code: '<path d="M16,9.14h-.86V6.64C15.14,3.45,13.39.86,10,.86S4.86,3.45,4.86,6.64v2.5H4a1,1,0,0,0-1,1v8a1,1,0,0,0,1,1H16a1,1,0,0,0,1-1v-8A1,1,0,0,0,16,9.14ZM6.58,6.41c0-2.27.93-4.12,3.42-4.12s3.43,1.85,3.43,4.12V9.14H6.58Zm5.06,6.24v2a1.07,1.07,0,0,1-1.06,1.06H9.42a1.07,1.07,0,0,1-1.06-1.06v-2a1.06,1.06,0,0,1,1.06-1.06h1.16A1.06,1.06,0,0,1,11.64,12.65Z"></path>' },
    holiday: { viewbox: '0 0 24 24', code: '<path d="m10.95,0h-1.9v2.86h1.9V0Zm5.76,1.95l-1.71,1.71,1.33,1.33,1.71-1.71-1.33-1.33ZM3.29,1.95l-1.34,1.34,1.71,1.71,1.34-1.34s-1.71-1.71-1.71-1.71Zm6.71,2.34c-3.16,0-5.71,2.56-5.71,5.71s2.56,5.71,5.71,5.71,5.71-2.56,5.71-5.71c0-3.15-2.56-5.71-5.71-5.71Zm10,4.76h-2.86v1.9h2.86v-1.9Zm-17.14,0H0v1.9h2.86v-1.9Zm13.48,5.95l-1.33,1.33,1.71,1.71,1.33-1.33s-1.71-1.71-1.71-1.71Zm-12.67,0l-1.71,1.71,1.33,1.33,1.71-1.71-1.34-1.33h0Zm7.29,2.14h-1.9v2.86h1.9v-2.86Z"></path>' },
};

function IP270SettingsSelect(lang, options, onChanged) {
    this.createNode("div", "height 44px; flex: 1; display: flex; width: 465px;");
    var select = this.add(new innovaphone.ui1.Node("select", "height: 44px; color:var(--c1); background-color: var(--forms); border-style: solid; border-width: 1px; border-color: var(--button-bg); border-radius: 5px; padding: 4px 16px 4px 16px; flex: 1;"));

    if (options && Array.isArray(options)) {
        options.forEach(function (opt) {
            select.add(new innovaphone.ui1.Node("option")).setAttribute("value", opt.value).addTranslation(lang, opt.text);
        });
    }

    select.addEvent("change", () => {
        if (onChanged) {
            onChanged(select.container.value);
        }
    });

    this.setValue = function (val) {
        select.container.value = val;
    };
}
IP270SettingsSelect.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsInputLabel(lang, label) {
    this.createNode("div", "height 21px; flex: 1;");
    this.add(new innovaphone.ui1.Node("label", "color:var(--c1);").addTranslation(lang, label));
}
IP270SettingsInputLabel.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsInputField(filter, onChanged) {
    this.createNode("div", "height 44px; flex: 1; display: flex; width: 465px;");
    var field = this.add(new innovaphone.ui1.Input("background-color: var(--forms); border-style: solid; border-width: 1px; border-color: var(--button-bg); border-radius: 5px; padding: 4px 16px 4px 16px; flex: 1; height: 34px; color:var(--c1);"));
    field.addEvent("input", function () {
        if (filter) field.setValue(field.getValue().replace(filter, ''));
    });
    field.addEvent("change", () => {
        if (onChanged) {
            onChanged(field.getValue());
        }
    });

    this.setValue = function (value) {
        field.setValue(value);
    }

    this.getValue = function (value) {
        return field.getValue();
    }
}
IP270SettingsInputField.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsInput(lang, label, filter, onChanged) {
    this.createNode("div", "gap: 7px; flex: 1; display: flex; flex-direction:column;");
    this.add(new IP270SettingsInputLabel(lang, label));
    var field = this.add(new IP270SettingsInputField(filter, function (value) {
        if (onChanged) {
            onChanged(value);
        }
    }));

    this.setValue = function (value) {
        field.setValue(value);
    }
}
IP270SettingsInput.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsDropdown(lang, label, options, onChanged) {
    this.createNode("div", "gap: 7px; flex: 1; display: flex; flex-direction:column;");
    this.add(new IP270SettingsInputLabel(lang, label));
    var select = this.add(new IP270SettingsSelect(lang, options, function (value) {
        if (onChanged) {
            onChanged(value);
        }
    }));

    this.setValue = function (value) {
        select.setValue(value);
    }
}
IP270SettingsDropdown.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsSwitch(lang, label, onChanged) {
    this.createNode("div", "gap: 7px; flex: 1; display: grid; grid-template-columns: auto 1fr;");
    var schalter = this.add(new innovaphone.ui1.Switch("width: 35px; height: 20px;", null, null, null, null, null, null, null, "10px"));
    this.add(new innovaphone.ui1.Node("label", "color:var(--c1);").addTranslation(lang, label));
    schalter.addEvent("change", () => {
        if (onChanged) {
            onChanged(schalter.getValue());
        }
    });
}
IP270SettingsSwitch.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsSlider(unit, stepSize, stepOffest, onChanged) {
    var steps = 10;
    var dots = [];
    this.createNode("div", "gap: 7px; flex: 1; display: grid; grid-template-columns: 1fr auto;");
    var sliderWrapper = this.add(new innovaphone.ui1.Node("div", "display: grid;"));
    sliderWrapper.add(new innovaphone.ui1.Node("div", "grid-area: 1/1; width: calc(100% - 24px); height: 6px; background: var(--forms); margin: 0 auto; align-self: center; border-radius: 3px; pointer-events: none;"));
    var sliderBackground = sliderWrapper.add(new innovaphone.ui1.Node("div", "display: flex; justify-content: space-between; align-items: center; padding: 0 10px; pointer-events: none; grid-area: 1 / 1; z-index: 2;"));
    for (var i = 0; i < steps; i++) {
        dots.push(sliderBackground.add(new innovaphone.ui1.Node("div", "width:10px; height:10px; background: var(--placeholder-bg); border-radius:50%;")));
    }
    var slider = sliderWrapper.add(new innovaphone.ui1.Input("position: relative; appearance: none; height: 6px; border-radius: 3px; background: transparent; align-self: center; grid-area: 1 / 1; z-index: 1;", 0, null, null, "range"));
    slider.setAttribute("min", stepOffest);
    slider.setAttribute("max", steps - 1 + stepOffest);
    slider.setAttribute("step", 1);

    var label = this.add(new innovaphone.ui1.Node("div", "background-color: var(--forms); border-radius: 10px; width: 64px; height: 32px; padding: 4px 8px; display: grid; grid-template-columns: 1fr auto; place-items: center;"));
    var valueNode = label.add(new innovaphone.ui1.Node("label", "color:var(--c1);").addText("50"));
    label.add(new innovaphone.ui1.Node("label", "color:var(--c1); text-align: left;").addText(unit));

    this.setValue = function (value) {
        if (value >= 0 && value < steps) {
            slider.setValue(value);
            Update(true);
        }
    };

    function Update(isRemoteUpdate) {
        const val = parseInt(slider.getValue());
        dots.forEach((dot, index) => {
            dot.setStyle("opacity", (index === (val - stepOffest)) ? "0" : "1");
        });
        valueNode.addText(val!=0 ? (val * stepSize) : "0");

        if (!isRemoteUpdate && onChanged) {
            onChanged(val);
        }
    };

    slider.addEvent('input', () => {
        Update(false);
    });

    Update(true);
}
IP270SettingsSlider.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsSliderWithLabel(lang, label, unit, stepSize, stepOffset, onChanged) {
    this.createNode("div", "gap: 7px; flex: 1; display: flex; flex-direction:column;");
    this.add(new IP270SettingsInputLabel(lang, label));
    var slider = this.add(new IP270SettingsSlider(unit, stepSize, stepOffset, function (value) {
        if (onChanged) {
            onChanged(value);
        }
    }));

    this.setValue = function (value) {
        slider.setValue(value);
    }
}
IP270SettingsSliderWithLabel.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsHeader(lang, icon, label) {
    this.createNode("div", "display: grid; grid-template-columns: auto 1fr; gap: 15px 10px; align-items: center; gap: 12px;");
    if(icon) this.add(new innovaphone.ui1.SvgInline("width: 24px; height: 24px; fill:var(--c1);", icon.viewbox, icon.code));
    this.add(new innovaphone.ui1.Node("label", "color:var(--c1); font-size: 20px;")).addTranslation(lang, label);
}
IP270SettingsHeader.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsDynamicList(lang, icon, label, onChanged) {
    this.createNode("div", "gap: 7px; flex: 1; display: flex; flex-direction:column;");
    var self = this;
    var rows = [];

    var container = this.add(new innovaphone.ui1.Node("div", "display: grid; grid-template-columns: 480px 24px; gap: 10px; align-items: center;"));

    container.add(new IP270SettingsHeader(lang, icon, label));
    var addBtn = container.add(new innovaphone.ui1.SvgInline("width: 24px; height: 24px; fill:var(--c1);", icons.add.viewbox, icons.add.code));

    addBtn.addEvent("click", function () { self.addRow(""); });

    function triggerChanged() {
        if (onChanged) {
            var values = rows.map(function (r) { return r.field.getValue(); })
                .filter(function (v) { return v !== ""; });
            onChanged(values.join(','));
        }
    }

    this.addRow = function (value) {
        var rowInput = container.add(new IP270SettingsInputField(null, function (value) { triggerChanged(); }));
        rowInput.setValue(value);
        var delBtn = container.add(new innovaphone.ui1.SvgInline("width: 24px; height: 24px; fill:var(--c1);", icons.del.viewbox, icons.del.code));

        var rowEntry = { field: rowInput, icon: delBtn };
        rows.push(rowEntry);

        delBtn.addEvent("click", function () {
            container.rem(rowInput);
            container.rem(delBtn);
            rows = rows.filter(function (r) { return r !== rowEntry; });
            triggerChanged();
        });
    }

    this.setValue = function (value) {
        rows.forEach(function (r) {
            container.rem(r.field);
            container.rem(r.icon);
        });
        rows = [];

        if (value && value.length > 0) {
            var parts = value.split(',');
            parts.forEach(function (part) {
                self.addRow(part.trim());
            });
        }
    }
}
IP270SettingsDynamicList.prototype = innovaphone.ui1.nodePrototype;

function IP270SettingsTimeRange(lang, labelFrom, labelTo, onChanged) {
    this.createNode("div", "display: grid; grid-template-columns: 150px 150px; gap: 20px;");
    var self = this;

    this.add(new innovaphone.ui1.Node("label", "color: var(--c1);")).addTranslation(lang, labelFrom);
    this.add(new innovaphone.ui1.Node("label", "color: var(--c1);")).addTranslation(lang, labelTo);
    var from = this.add(new innovaphone.ui1.Input("background-color: var(--forms); border-style: solid; border-width: 1px; border-color: var(--button-bg); border-radius: 5px; padding: 4px 16px 4px 16px; height: 34px; color:var(--c1); text-align: center;", "", null, null, "time"));
    var to = this.add(new innovaphone.ui1.Input("background-color: var(--forms); border-style: solid; border-width: 1px; border-color: var(--button-bg); border-radius: 5px; padding: 4px 16px 4px 16px; height: 34px; color:var(--c1); text-align: center;", "", null, null, "time"));

    from.container.setAttribute("step", "60");
    to.container.setAttribute("step", "60");

    from.container.setAttribute("inputmode", "none");
    to.container.setAttribute("inputmode", "none");

    from.addEvent("click", function () {
        if (typeof from.container.showPicker === "function") {
            from.container.showPicker();
        }
    });

    to.addEvent("click", function () {
        if (typeof to.container.showPicker === "function") {
            to.container.showPicker();
        }
    });

    function timeToSecondsOfDay(timeString) {
        const [h, m] = timeString.split(':');
        return (parseInt(h) * 3600) + (parseInt(m) * 60);
    }

    function secondsOfDayToTime(totalSeconds) {
        var h = Math.floor(totalSeconds / 3600);
        var m = Math.floor((totalSeconds % 3600) / 60);

        var hours = h < 10 ? "0" + h : h;
        var minutes = m < 10 ? "0" + m : m;

        return hours + ":" + minutes;
    }

    function triggerChanged() {
        if (onChanged) {
            onChanged(timeToSecondsOfDay(from.getValue()), timeToSecondsOfDay(to.getValue()));
        }
    }

    from.addEvent("change", triggerChanged);
    to.addEvent("change", triggerChanged);

    this.setToValue = function (value) {
        to.setValue(secondsOfDayToTime(value));
    }

    this.setFromValue = function (value) {
        from.setValue(secondsOfDayToTime(value));
    }
}
IP270SettingsTimeRange.prototype = innovaphone.ui1.nodePrototype;

function PageIP270LockscreenSettings(owner, lang, send) {
    var container = this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; overflow: auto; background-color: var(--bg1);");

    var lockScreenSettings = container.add(new innovaphone.ui1.Node("div", "display: flex; flex-direction: column; padding: 20px 16px 20px 16px; gap: 20px;"));
    lockScreenSettings.add(new IP270SettingsHeader(lang, icons.blocked, "lockscreen"));

    var pinCode = lockScreenSettings.add(new IP270SettingsInput(lang, "pinCode", /[^0-9]/g, function (value) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "lockScreenPin": { "value": value, "force": false } } });
    }));
    //lockScreenSettings.add(new IP270SettingsSwitch(lang, "autolock", function (value) {
    //    if (send) send({ mt: "ClientConfig", adminSettings: { "lockScreenTimeout": { "value": value ? 5 : 0, "force": false } } });
    //}));
    var lockScreenTimeoutSlider = lockScreenSettings.add(new IP270SettingsSlider("min", 5, 0, function (value) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "lockScreenTimeout": { "value": value * 5, "force": false } } });
    }));

    var clockOptions = [
        { text: "clockModeAnalog", value: "analog" },
        { text: "clockModeDigital", value: "digital" },
        { text: "clockModeLed", value: "led" }
    ];
    var clockDropdown = lockScreenSettings.add(new IP270SettingsDropdown(lang, "clockMode", clockOptions, function (value) {
        send({ mt: "ClientConfig", adminSettings: { "lockScreenClock": { "value": value, "force": false } } });
    }));

    container.add(new innovaphone.ui1.Node("div", " background-color: var(--bg3); height: 2px;"));

    var emergencyNumberSettings = container.add(new innovaphone.ui1.Node("div", "display: flex; flex-direction: column; padding: 20px 16px 20px 16px; gap: 20px;"));
    var emergencyNumbers = emergencyNumberSettings.add(new IP270SettingsDynamicList(lang, icons.call, "emergencyNumbers", function (value) {
        send({ mt: "ClientConfig", adminSettings: { "lockScreenEmergencyNumbers": { "value": value, "force": false } } });
    }));

    owner.onmessage.attach(function (sender, obj) {
        if (obj.mt == "ClientConfig") {
            if (obj.lockScreenPin.value.length > 0) pinCode.setValue("****");
            if (obj.lockScreenClock) clockDropdown.setValue(obj.lockScreenClock.value);
            if (obj.lockScreenTimeout) lockScreenTimeoutSlider.setValue((parseInt(obj.lockScreenTimeout.value) / 5));
            if (obj.lockScreenEmergencyNumbers) emergencyNumbers.setValue(obj.lockScreenEmergencyNumbers.value);
        }
    });
}
PageIP270LockscreenSettings.prototype = innovaphone.ui1.nodePrototype;

function PageIP270DisplaySettings(owner, lang, send) {
    var container = this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; overflow: auto; background-color: var(--bg1);");

    var displaySettings = container.add(new innovaphone.ui1.Node("div", "display: flex; flex-direction: column; padding: 20px 16px 20px 16px; gap: 20px;"));
    displaySettings.add(new IP270SettingsHeader(lang, icons.holiday, "brightness"));


    var backlightMaxSlider = displaySettings.add(new IP270SettingsSliderWithLabel(lang, "backlight", "%", 10, 1, function (value) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "backlightMax": { "value": (value + 1) * 10, "force": false } } });
    }));

    var backlightIdleSlider = displaySettings.add(new IP270SettingsSliderWithLabel(lang, "backlightIdle", "%", 10, 1, function (value) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "backlightIdle": { "value": (value + 1) * 10, "force": false } } });
    }));

    displaySettings.add(new IP270SettingsHeader(lang, icons.holiday, "energysave"));
    var energySavingRange = displaySettings.add(new IP270SettingsTimeRange(lang, "from", "to", function (from, to) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "energySavingStart": { "value": from, "force": false } } });
        if (send) send({ mt: "ClientConfig", adminSettings: { "energySavingStop": { "value": to, "force": false } } });
    }));


    owner.onmessage.attach(function (sender, obj) {
        if (obj.mt == "ClientConfig") {
            if (obj.backlightMax) backlightMaxSlider.setValue((obj.backlightMax.value / 10) - 1);
            if (obj.backlightIdle) backlightIdleSlider.setValue((obj.backlightIdle.value / 10) - 1);
            if (obj.energySavingStart) energySavingRange.setFromValue(obj.energySavingStart.value);
            if (obj.energySavingStop) energySavingRange.setToValue(obj.energySavingStop.value);
        }
    });
}
PageIP270DisplaySettings.prototype = innovaphone.ui1.nodePrototype;

function PageIP270AudioSettings(owner, lang, send) {
    var container = this.createNode("div", "position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; overflow: auto; background-color: var(--bg1);");

    var audioSettings = container.add(new innovaphone.ui1.Node("div", "display: flex; flex-direction: column; padding: 20px 16px 20px 16px; gap: 20px;"));
    //audioSettings.add(new IP270SettingsHeader(lang, icons.blocked, "audio"));


    var ringerVolumeSlider = audioSettings.add(new IP270SettingsSliderWithLabel(lang, "ringerVolume", "%", 10, 1, function (value) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "ringerVolume": { "value": (value + 1) * 10, "force": false } } });
    }));

    var handsetVolumeSlider = audioSettings.add(new IP270SettingsSliderWithLabel(lang, "handsetVolume", "%", 10, 1, function (value) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "handsetVolume": { "value": (value + 1) * 10, "force": false } } });
    }));

    var handsfreeVolumeSlider = audioSettings.add(new IP270SettingsSliderWithLabel(lang, "handsfreeVolume", "%", 10, 1, function (value) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "handsfreeVolume": { "value": (value + 1) * 10, "force": false } } });
    }));

    var headsetVolumeSlider = audioSettings.add(new IP270SettingsSliderWithLabel(lang, "headsetVolume", "%", 10, 1, function (value) {
        if (send) send({ mt: "ClientConfig", adminSettings: { "headsetVolume": { "value": (value + 1) * 10, "force": false } } });
    }));

    owner.onmessage.attach(function (sender, obj) {
        if (obj.mt == "ClientConfig") {
            if (obj.ringerVolume) ringerVolumeSlider.setValue((obj.ringerVolume.value / 10) - 1);
            if (obj.handsetVolume) handsetVolumeSlider.setValue((obj.handsetVolume.value / 10) - 1);
            if (obj.handsfreeVolume) handsfreeVolumeSlider.setValue((obj.handsfreeVolume.value / 10) - 1);
            if (obj.headsetVolume) headsetVolumeSlider.setValue((obj.headsetVolume.value / 10) - 1);
        }
    });
}
PageIP270AudioSettings.prototype = innovaphone.ui1.nodePrototype;