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

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

function getGroup(s, name) {
    console.log('name: ',name, ', id: '.ClientID);
    reqJSON(s, "http://" + hostPort + "/getblock?path=" + name
            + "&id=" + clientID, successHandler, errorHandler);
}

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

function createContent(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;

        if (message.title == 'modules') {
            let row = createRowForModules(component);
            content.appendChild(row);
        } else {
            let row = createRowForParameters(component);
            content.appendChild(row);
        }
    }
    return content;
}

/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// ROW

function createRowForModules(component) {
    let left = createLeftColumnForModules(component);
    left.id = component.name;
    left.setAttribute('name', 'component.title');

    let right = createRightColumnForModules(component);
    let row = appendToContent(left, right);
    
    row.onclick = function () {
        getGroup(s, component.title);
    }
    row.classList.add('row-clickable');
    return row;
}

function createRowForParameters(component) {
    let left = document.createElement('span');
    left.classList.add('col-left');
    left.innerHTML = component.title;
    let right = document.createElement('span');
    right.classList.add('col-right-parameters');
    let value = document.createElement('span');
    value.classList.add('col-right-value');
    value.setAttribute('name', component.name);
    value.__ctype__ = 'rdonly';
    right.appendChild(value);
    
    if (component.type == 'input' ||
        component.type == 'pushbutton' ||
        component.type == 'checkbox' ||
        component.type == 'enum'
    ) {
        var input_element;
        switch (component.type) {
            case 'enum':
                input_element = createEnum(component);
                break;
            case 'pushbutton':
                input_element = createPushbutton(component);
                break;  
            case 'input':
                input_element = createInput(component);
                break;
            case 'checkbox':
                input_element = createCheckbox(component);
                break;
        }
        input_element.classList.add('input-element', 'input-element-hidden');
        if (component.type != 'pushbutton') {
            let icon_edit = createIconEdit();
            right.appendChild(icon_edit);
        }
        right.appendChild(input_element);
    }
    return appendToContent(left, right);

    function createIconEdit () {
        let icon_edit = document.createElement('img');
        icon_edit.setAttribute('src', 'res/icon_edit.png');
        icon_edit.classList.add('modules-icon', 'edit-icon');

        icon_edit.onclick = function () {
            let is_hidden = input_element.classList.contains('input-element-hidden');
            hideInputElements();
            if (is_hidden) {
                input_element.classList.remove('input-element-hidden');
            }
        }

        return icon_edit;
    }
}

function appendToContent(left, right) {
    let row = document.createElement('div');
    row.classList.add("row");
    row.appendChild(left);
    row.appendChild(right);
    return row;
}

/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// LEFT COLUMN

function createLeftColumnForModules(component) {
    var left = document.createElement('span');
    left.classList.add('col-left');
    if (component.statusname) {
        left.appendChild(createStatusIcon(component));
    }
    let modules_title = document.createElement('span');
    modules_title.classList.add('modules-title');
    modules_title.innerHTML = component.title;
    left.appendChild(modules_title);
    if (component.statusname) {
        let status_info = document.createElement('span');
        status_info.classList.add('status-info');
        status_info.setAttribute('name', component.title + '-info');
        left.appendChild(status_info);
    }
    if (component.info) {
        let icon_info = createInfoIcon(component);
        left.appendChild(icon_info);
        left.appendChild(createInfoBox(component));
    }
    return left;

    function createStatusIcon(component) {
        let icon_status = document.createElement('img');
        icon_status.setAttribute('src', 'res/icon_status.png');
        icon_status.setAttribute('name', component.title + ':status');
        icon_status.classList.add('modules-icon', 'status-icon');
        return icon_status;
    }

    function createInfoIcon(component) {
        let icon_info = document.createElement('img');
        icon_info.setAttribute('src', 'res/icon_info.png');
        icon_info.classList.add('modules-icon', 'icon-info');
        if (isTouchDevice) {
            icon_info.onclick = function (event) {
                event.stopPropagation()
                icon_info.nextSibling.classList.toggle("info-box-visible-by-click");
            }
        }
        return icon_info;
    }

    function createInfoBox(component) {
        // Creates info-box, which isn't visible by default but can be displayed.
        let info_box = document.createElement('span');
        info_box.classList.add("info-box");
        info_box.innerHTML = '<b>' + component.title + '</b>: ' + component.info;
        return info_box;
    }
}

/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// RIGHT COLUMN

function createRightColumnForModules(component) {
    var right = document.createElement('span');
    right.classList.add('col-right', 'col-right-modules');
    let value = document.createElement('span');
    value.classList.add('col-right-value');
    value.setAttribute('name', component.name);
    value.__ctype__ = component.type;
    right.appendChild(value);
    if (component.targetname) {

        var input_element = createInput(component);
        input_element.classList.add('input-element', 'input-element-hidden');
        
        let icon_edit = createIconEdit();
        right.appendChild(icon_edit);
        
        right.appendChild(input_element);
    }
    return right;

    function createIconEdit () {
        let icon_edit = document.createElement('img');
        icon_edit.setAttribute('src', 'res/icon_edit.png');
        icon_edit.classList.add('modules-icon', 'edit-icon');

        icon_edit.onclick = function (event) {
            event.stopPropagation()
            let is_hidden = input_element.classList.contains('input-element-hidden');
            hideInputElements();
            if (is_hidden) {
                input_element.classList.remove('input-element-hidden');
            }
        }

        return icon_edit;
    }
}

/* ---------------------------------------------------------------------------------- */
// input elements

function createPushbutton(component) {
    // Creates row-element containing a push button
    var button = createInputElement(component, 'button', 'push-button');
    button.setAttribute('type', 'button');
    
    button.onclick = function () {
        console.log('click pushbutton');
        sendCommand(s, component.command);
    }
    return button;
}

function createInput(component) {
    // Creates row-element containing input-item.
    var command = component.command;
    var input = createInputElement(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.key == "Escape") {
            // User decided to cancel
            let input = e.target;
            input.value = input.oldValue;
            resizeTextfield(input);
            var row = input.closest('div');
            row.style.backgroundColor = "white";
            hideInputElements();
        }
    }

    input.onclick = function (e) {
        e.stopPropagation();
    }

    input.onfocus = function () {
        input.oldValue = input.value;
        if (isTouchDevice)
            setTimeout(function () {
                posTextfield(s, left);
            }, 1);
    }

    input.onblur = function () {
        if (prompt) {
            return false;
        }
        var row = input.closest('div');
        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>"
                + component.name + "</b> from <b>" + actualValue
                + "</b> to <b>" + value + "</b>?", 
        function () {
            // User decided to proceed.
            row.style.backgroundColor = "orangered";
            // Request for command
            sendCommand(s, command + " " + value);
            resizeTextfield(input);
            prompt = false;
            hideInputElements();
        }, function () {
            // User decided to cancel
            input.value = input.actualValue;
            resizeTextfield(input);
            row.style.backgroundColor = "white";
            prompt = false;
            hideInputElements();
        });
    }

    var form = document.createElement('form');
    form.onsubmit = function (e) {
        e.preventDefault();
        var row = form.closest('div');
        row.style.backgroundColor = "orangered";
        // Request for command
        input.actualValue = input.value;
        if (component.targetname) {
            sendCommand(s, component.targetname + " " + input.value);
        } else {
            sendCommand(s, component.name + " " + input.value);
        }
        input.blur();
        hideInputElements();
    };
    form.appendChild(input);
    return form;

    function posTextfield(s, left) {
        if (debug_group_daniel) {
            console.log("%cfunction: posTextfield", "color:white;background:salmon");
        }
    
        // var content = swiper[s].slides[swiper[s].activeIndex].childNodes[1];
        // var row = left.parentNode;
        // content.scrollTop = row.offsetTop - 30;
    
        // ---------------------> Not working anymore since swiper was removed!!!
    }
}

function createCheckbox(component) {
    // Creates row-element containing checkbox-item
    var input = createInputElement(component, 'input', 'parameter-checkbox');
    input.type = "checkbox";
    
    input.onclick = function () {
        handleCheckbox();
    }

    function handleCheckbox() {
        console.log('handle checkbox');
        let row = input.closest('div');
        row.style.backgroundColor = "orangered";
        console.log('send ', input.checked);
        sendCommand(s, component.command + " " + input.checked);
        // hideInputElements();
    };

    let right = document.createElement('span');
    right.appendChild(input);
    return right;
}

function createEnum(component) {
    // Creates row-element containing dropdown-selection.
    var buttons = component.enum_names;
    var select = createInputElement(component, 'select', 'select-params');

    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.oninput = function () {
        let row = select.closest('div');
        row.style.backgroundColor = "orangered";
        let index = select.value - 1;
        console.log('send', buttons[index].title);
        sendCommand(s, component.command + " " + select.value);
        // hideInputElements();
    };

    select.onfocus = function () {
        // select.oldIndex = select.selectedIndex;
        console.log(select.selectedValue);
    }

    var right = document.createElement('span');
    right.appendChild(select);
    return right;
}

function createInputElement(component, tag='span', cls='col-right-modules') {
    var input_element = document.createElement(tag);
    input_element.classList.add('col-right');
    if (cls)
        input_element.classList.add(cls);
    if (component.targetname) {
        input_element.setAttribute('name', component.targetname);
    } else {
        input_element.setAttribute('name', component.name);
    }
    // Add DOM-property
    input_element.__ctype__ = component.type;
    return input_element;
}

/* ---------------------------------------------------------------------------------- */

function hideInputElements(){
    let input_elements = document.getElementsByClassName('input-element');
    for (let i = 0; i < input_elements.length; i++) {
        input_elements[i].classList.add('input-element-hidden');
    }
}

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

/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
// CONTENT

function appendToGridElement(s, title, type, content) {
    var panel = document.createElement('div');
    panel.classList.add("panel");

    titlewrapper = document.createElement('span');
    titlewrapper.innerHTML = title;
    panel.appendChild(titlewrapper);

    var gridContainer = document.createElement('div');
    gridContainer.classList.add("grid-container");
    // Store type so it can be found easiely later.
    gridContainer.slideType = type;
    gridContainer.appendChild(panel);
    gridContainer.appendChild(content);

    var gridelements = document.getElementsByClassName('grid-element');
                    gridelements[s].innerHTML = "";
                    gridelements[s].appendChild(gridContainer);
}

// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/* ---------------------------------------------------------------------------------- */
// obsolete...

// function createPushbutton_row(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 = createInputElement(component);
//     right.classList.add("push-button");

//     row = appendToContent(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(component) {
//     // Creates row-element containing input-item.
//     var name = component.name;
//     var command = component.command;
//     var left = createTitle(component);

//     var input = createInputElement(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
//             input.actualValue = input.value;
//             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";
//                         input.actualValue = value;
//                         // 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 = createInputElement(component);
//     right.appendChild(form);
//     return appendToContent(left, right);

//     function posTextfield(s, left) {
//         if (debug_group_daniel) {
//             console.log("%cfunction: posTextfield", "color:white;background:salmon");
//         }
    
//         // var content = swiper[s].slides[swiper[s].activeIndex].childNodes[1];
//         // var row = left.parentNode;
//         // content.scrollTop = row.offsetTop - 30;
    
//         // ---------------------> Not working anymore since swiper was removed!!!
//     }
// }

// function createCheckbox_row(component) {
//     // Creates row-element containing checkbox-item
//     var command = component.command;
//     var left = createTitle(component);
//     var input = createInputElement(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(left, right);
// }

// function createEnum_row(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 = createInputElement(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(left, right);
// }

// ...obsolete
/* ---------------------------------------------------------------------------------- */
// The following two functions seem unreachable

/* ########## Is this function used? How? Where? ########## */
// function create_group_row(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("row");
//     row.tabIndex = "0";

//     console.log('createGroupRow');

//     row.onclick = function () {
//         var slideNames = getSlideNames();
//         slideNames[0] = 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("row");
//         row.innerHTML = "console";
//     }
//     row.innerHTML = title;
//     return row;
// }

/* ########## Is this function used? How? Where? ########## */
// function create_rdonly_row(component) {
//     // Creates row-element containing link AND read-only-item.
//     var link = component.link;
//     if (!link)  // simple rdonly
//         return appendToContent(createTitle(component),
//                                createInputElement(component));

//     // with link
//     var left = document.createElement('a');
//     left.innerHTML = component.title;

//     console.log('ccc')

//     left.id = component.name;

//     row = appendToContent(left, createInputElement(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");
//     return row;
// }
