// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % GROUP

var writePermissionTimeout; // Sets writePermission to 'false, restarts by
// user-interaction.

var prompt = false // True while a prompt is opened.

function getGroup(s, name) {
    var found = false;
    if (name == "") {
      swiper[s].slideTo(defaultSlidePos(s));
      return;
    }
    for (var i = 0; i < swiper[s].slides.length; i++) {
        var slideType = swiper[s].slides[i].slideType;
        if (slideType == name) {
            found = true;
            swiper[s].slideTo(i);
        }
    }
    if (!found && name != "console" && name != "graphics") {
        // Server-request for group.
        reqJSON(s, "http://" + hostPort + "/getblock?path=" + name
                + "&id=" + clientID, successHandler, errorHandler);
    }
}

function sendCommand(s, command) {
    reqJSON(s, "http://" + hostPort + "/sendcommand?command=" + command
            + "&id=" + clientID, successHandler, errorHandler);
}

function createContent(s, message) {
    // Depending on the message received from the server the content of the
    // group is created dynamically. Handles draw-message.

    var content = document.createElement('div');
    content.classList.add("content");
    // Process components of the message
    for (var i = 0; i < message.components.length; i++) {
        var component = message.components[i];
        if (!("title" in component))
            component.title = component.name;
        if (!("command" in component))
            component.command = component.name;
        createFunc = window['create_' + component.type + '_row']
        if (createFunc)
            content.appendChild(createFunc(s, component))
    }
    return content;
}

function gotoGroups(slideNames) {
    slideNames = slideNames.split("%20");
    var l = Math.min(MAXBLOCK,slideNames.length);
    document.title = "SEA "+ clientTitle + " " + slideNames.join(" ");
    for (var s=0; s<l; s++) {
      getGroup(s, slideNames[s]);
    }
}

function create_group_row(s, component) {
    // Creates row-element containing link.
    var title = component.title;

    var row = document.createElement('row');
    row.id = component.name;
    row.name = title;
    row.classList.add("interactive", "row", "link");
    row.tabIndex = "0";

    row.onclick = function () {
        var slideNames = getSlideNames();
        slideNames[s] = component.name;
        document.title = "SEA "+ clientTitle + " " + slideNames.join(" ");
        history.pushState({func: "gotoGroups", funarg: slideNames.join("%20")}, document.title, "#" + slideNames.join("%20"));
        getGroup(s, component.name);
    }

    if (title === "console" || title === "device config") {
        row.classList.add("interactive", "row", "link", "link-static");
        row.innerHTML = "console";
    }
    row.innerHTML = title;
    return row;
}

function create_rdonly_row(s, component) {
    // Creates row-element containing link AND read-only-item.

    var link = component.link;
    if (!link)  // simple rdonly
        return appendToContent(component, createTitle(component),
                               createParElement(component));

    // with link
    var left = document.createElement('a');
    left.classList.add("col-left");
    left.innerHTML = component.title;

    left.id = component.name;
    left.name = component.title;
    left.classList.add("interactive", "link");

    row = appendToContent(component, left, createParElement(component));
    row.onclick = function () {
        this.style.backgroundColor = "orangered";
        left.click();
    }
    if (link.charAt(0) == ':') {
      left.href = "http://" + location.hostname + link + "/";
    } else {
      left.href = link;
    }

    row.classList.add("row", "clickable");
    return row;
}

function create_rdlink_row(s, component) {
    // Creates row-element containing link AND read-only-item.
    var name = component.name;

    var left = createTitle(component);
    left.id = component.name;
    left.name = component.title;  // or setAttribute('name'.. ?
    left.classList.add("interactive", "link");

    left.onclick = function () {
        getGroup(s, component.title);
    }
    return appendToContent(component, left, createParElement(component));
}

function create_pushbutton_row(s, component) {
    // Creates row-element containing a push button

    var name = component.name;
    var command = component.command;
    var left = createTitle(component);
    
    left.id = component.name;
    left.name = component.title;

    var right = createParElement(component);
    right.classList.add("clickable", "push-button");

    row = appendToContent(component, left, right);
    right.onclick = function () {
        if (writePermission) {
            var row = left.parentNode;
            right.style.backgroundColor = "orangered";
            // Request for command
            sendCommand(s, command);
        } else {
            prompt = true;
            alertify.confirm("", "You are connected with <b>" + clientTitle
                    + "</b>. <br>"
                    + "Are you sure you want to modify things here?",
                    function () {
                        // User decided to proceed.
                        writePermission = true;
                        writePermissionTimeout = setTimeout(function () {
                            writePermission = false;
                        }, 3600000);
                        var row = left.parentNode;
                        row.style.backgroundColor = "orangered";
                        // Request for command
                        sendCommand(s, command);
                        prompt = false;
                    }, function () {
                        // User decided to cancel
                        prompt = false;
                    });
        }
    }

    row.classList.add("row");
    return row;
}

function create_input_row(s, component) {
    // Creates row-element containing input-item.

    var name = component.name;
    var command = component.command;

    if (component.info) {
        var infoBox = createInfo(component);
    }
    var left = createTitle(component);

    var input = createParElement(component, 'input', 'input-text');
    input.type = "text";
    input.style.width = "100px";
    input.addEventListener("focus", function(evt) {
        let elm = evt.target;
        setTimeout(function(){elm.setSelectionRange(0, elm.value.length);},0);
    });

    input.onkeydown = function (e) {
        if (e.which === 27 || e.key == "Escape") {
            // User decided to cancel
            input.value = intput.oldValue;
            resizeTextfield(input);
            var row = left.parentNode;
            row.style.backgroundColor = "white";
        }
    }

    input.onfocus = function () {
        input.oldValue = input.value;

        if (isTouchDevice)
            setTimeout(function () {
                posTextfield(s, left);
            }, 1);
    }

    input.onblur = function () {
        if (prompt) {
            return false;
        }
        var row = left.parentNode;
        var value = input.value;
        let oldValue = 'oldValue' in input ? input.oldValue : value;
        if (!('actualValue' in input)) input.actualValue = oldValue;
        actualValue = input.actualValue;
        if (value == actualValue || value == oldValue ||
            parseFloat(value) == parseFloat(actualValue) || parseFloat(value) == parseFloat(oldValue)) {
            input.value = actualValue;
            // nothing to do.
            row.style.backgroundColor = "white";
            return false;
        }
        // User changed value and moved focus to other object.
        alertify.confirm("", "You changed a field without pressing the return key.<br>"
                + "Hint: press ESC for leaving a field unchanged.<b>"
                + "You are connected with <b>" + clientTitle + "</b>.<br>"
                + "Are you sure you want to change the value of<br><b>"
                + name + "</b> from <b>" + actualValue
                + "</b> to <b>" + value + "</b>?", function () {
            // User decided to proceed.
            writePermission = true;
            writePermissionTimeout = setTimeout(function () {
                writePermission = false;
            }, 3600000);
            row.style.backgroundColor = "orangered";
            // Request for command
            sendCommand(s, command + " " + value);
            resizeTextfield(input);
            prompt = false;
        }, function () {
            // User decided to cancel
            input.value = input.actualValue;
            resizeTextfield(input);
            row.style.backgroundColor = "white";
            prompt = false;
        });
    }

    var form = document.createElement('form');
    form.onsubmit = function (e) {
        e.preventDefault();
        if (writePermission) {
            var row = left.parentNode;
            row.style.backgroundColor = "orangered";
            // Request for command
            sendCommand(s, name + " " + input.value);
            input.blur();
        } else {
            var value = input.value
            prompt = true;
            alertify.confirm("", "You are connected with <b>" + clientTitle
                    + "</b>. <br>"
                    + "Are you sure you want to modify things here?",
                    function () {
                        // User decided to proceed.
                        writePermission = true;
                        writePermissionTimeout = setTimeout(function () {
                            writePermission = false;
                        }, 3600000);
                        var row = left.parentNode;
                        row.style.backgroundColor = "orangered";
                        // Request for command
                        sendCommand(s, command + " " + value);
                        resizeTextfield(input);
                        prompt = false;
                    }, function () {
                        // User decided to cancel
                        input.value = input.oldValue;
                        resizeTextfield(input);
                        prompt = false;
                    });
        }
    };
    form.appendChild(input);
    var right = createParElement(component);
    right.appendChild(form);
    return appendToContent(component, left, right);
}

function posTextfield(s, left) {
    var content = swiper[s].slides[swiper[s].activeIndex].childNodes[1];
    var row = left.parentNode;
    content.scrollTop = row.offsetTop - 30;
}

function resizeTextfield(input) {
    if (input.value.length > input.size * 12 / 20) {
        var str0 = window.getComputedStyle(input).fontSize;
        var str1 = str0.substring(0, str0.length - 2);
        if (input.value.length < 43) {
            input.style.width = input.value.length * str1 * 12 / 20 + "px";
        }
    } else {
        input.style.width = "100px";
    }
}

function create_checkbox_row(s, component) {
    // Creates row-element containing checkbox-item
    var command = component.command;

    var left = createTitle(component);

    var input = createParElement(component, 'input', 'parameter-checkbox');
    input.type = "checkbox";

    input.onkeyup = function (e) {
        if (e.keyCode === 32) {
            handleCheckbox();
        }
    }

    var label = document.createElement('label');
    label.for = input;
    label.classList.add("parameter-label");

    label.onclick = function () {
        handleCheckbox();
    }

    function handleCheckbox() {
        if (writePermission) {
            var row = left.parentNode;
            row.style.backgroundColor = "orangered";
            if (input.checked) {
                var value = "0";
                input.checked = false;
            } else {
                var value = "1";
                input.checked = true;
            }
            // Request for command
            sendCommand(s, command + " " + value);
        } else {
            alertify.confirm("", "You are connected with <b>" + clientTitle
                    + "</b>. <br>"
                    + "Are you sure you want to modify things here?",
                    function () {
                        // User decided to proceed.
                        writePermission = true;
                        writePermissionTimeout = setTimeout(function () {
                            writePermission = false;
                        }, 3600000);
                        var row = left.parentNode;
                        row.style.backgroundColor = "orangered";
                        if (input.checked) {
                            var value = "0";
                            input.checked = false;
                        } else {
                            var value = "1";
                            input.checked = true;
                        }
                        // Request for command
                        sendCommand(s, command + " " + value);
                    }, function () {
                        // User decided to cancel
                    });
        }
    };

    var right = document.createElement('span');
    right.classList.add("col-right");
    right.appendChild(input);
    right.appendChild(label);
    return appendToContent(component, left, right);
}

function create_enum_row(s, component) {
    // Creates row-element containing dropdown-selection.
    var name = component.name;
    var command = component.command;
    var buttons = component.enum_names;

    var left = createTitle(component);

    var select = createParElement(component, 'select', 'select-params');

    select.onfocus = function () {
        select.oldIndex = select.selectedIndex;
    }

    select.oninput = function () {
        if (writePermission && component.title != "device config") {
            var row = left.parentNode;
            row.style.backgroundColor = "orangered";
            // Request for command
            sendCommand(s, command + " " + this.value);
        } else {
            alertify.confirm("", "You are connected with <b>" + clientTitle
                    + "</b>. <br>"
                    + "Are you sure you want to modify things here?",
                    function () {
                        // User decided to proceed.
                        writePermission = true;
                        writePermissionTimeout = setTimeout(function () {
                            writePermission = false;
                        }, 3600000);
                        var row = left.parentNode;
                        row.style.backgroundColor = "orangered";
                        // Request for command
                        sendCommand(s, command + " " + select.value);
                    }, function () {
                        // User decided to cancel
                        select.value = select.options[select.oldIndex].value
                    });
        }
    };

    for (var i = 0; i < buttons.length; i++) {
        var option = document.createElement('option');
        option.type = "enum";
        option.classList.add("option-params");
        option.value = buttons[i].value;
        option.appendChild(document.createTextNode(buttons[i].title));
        select.add(option);
    }
    select.style.display = "none";

    var right = document.createElement('span');
    right.classList.add("col-right");
    right.appendChild(select);
    return appendToContent(component, left, right);
}

function createTitle(component) {
    // Creates left side of row-tag containing title. Title may hold additional
    // information, which is shown, when title-tag is clicked.

    var left = document.createElement('span');
    if (component.info) {
        left.classList.add("col-left", "event-toggle-info");

        left.onclick = function () {
            var infoBox = left.parentNode.childNodes[0];
            if (infoBox.style.display == "none") {
                infoBox.style.display = "block";
            } else {
                infoBox.style.display = "none";
            }
        }

        left.innerHTML = component.title + "<sup><b>(i)</b></sup>";
    } else {
        left.classList.add("col-left");
        left.innerHTML = component.title;
    }
    return left;
}

function createParElement(component, tag='span', cls='col-right') {
    var right = document.createElement(tag);
    if (cls)
        right.classList.add(cls);
    // right.name = is not sufficient, getElementsByName would not work
    right.setAttribute('name', component.name);
    right.__ctype__ = component.type;
    return right;
}

function createInfo(component) {
    // Creates info-box, which isn't visible by default but can be displayed.

    var infoBox = document.createElement('div');
    infoBox.classList.add("info-box");

    infoBox.onclick = function () {
        infoBox.style.display = "none";
    }

    infoBox.innerHTML = component.info;
    return infoBox;
}

function appendToContent(component, left, right) {
    // Creates row-tag containing infoBox (not visible by default), left side
    // (span) and right side (span).

    var row = document.createElement('div');
    row.classList.add("row");
    if (component.info) {
        row.appendChild(createInfo(component));
    }
    row.appendChild(left);
    row.appendChild(right);
    return row;
}
