/* Color library set color */
["click", "touchend"].forEach(function(eventType){
    [].forEach.call(document.getElementsByClassName("getcolor-colorsblock__color"), function(colorButton){
        colorButton.addEventListener(eventType, (e) => {
            rgbaValues = getComputedStyle(e.target).getPropertyValue("background-color");
            rgbaValues = rgbaValues.replace(/[^\d,]/g, '').split(",");
            rgbaValues.push("1.0");
            setValuesToRgbaFields(rgbaValues);
        });
    });
});
/* Move color picker cursor function */
function moveColorCursor(colorCursor, movingArea) {
    colorCursor = document.getElementById(colorCursor);
    movingArea = document.getElementById(movingArea);
    
    movingArea.onmousedown = function(e) {
        var coords = getCoords(colorCursor);
        var shiftX = movingArea.offsetLeft - coords.left;
        var shiftY = movingArea.offsetTop - coords.top;
  
        colorCursor.style.position = 'absolute';
        moveAt(e);
        function moveAt(e) {
            var bounds = movingArea.getBoundingClientRect();
            var blockSizeX = parseInt(getComputedStyle(movingArea).width);
            var blockSizeY = parseInt(getComputedStyle(movingArea).height);
            var x = parseInt(e.clientX - bounds.left);
            var y = parseInt(e.clientY - bounds.top);
            
            if (x >= blockSizeX)
                x = parseInt(blockSizeX);
            if (x <= 0)
                x = 0;
            if (y >= blockSizeY)
                y = parseInt(blockSizeY);
            if (y <= 0)
                y = 0;
            
            colorCursor.style.left = parseInt(x - 6) + 'px';
            colorCursor.style.top = parseInt(y - 6) + 'px';
            movingArea.setAttribute("data-sat", Math.abs(parseInt(parseInt(x) / parseInt(blockSizeX) * 100)));
            movingArea.setAttribute("data-light", parseInt(HSVtoHSL(getHueValuePicker(), 
                Math.abs(parseInt(x) / parseInt(blockSizeX) * 100),
                Math.abs(100 - parseInt(y) / parseInt(blockSizeY) * 100))[2]));
            
            applyColorChanges();
            updateResultButtonColor();
        }
        function updateResultButtonColor() {
            let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
            let rgbaFields = document.getElementsByClassName("getcolor-rgbacodeblock__rgba");
            let rgbaValues = [parseInt(rgbaFields[0].value),
                            parseInt(rgbaFields[1].value),
                            parseInt(rgbaFields[2].value),
                            parseFloat(rgbaFields[3].value)];
            switchAndSetMainResultButtonBackground(currentState, rgbaValues);
        }
        document.onmousemove = function(e) {
            moveAt(e);
        };
        document.onmouseup = function() {
            document.onmousemove = null;
            document.onmouseup = null;
        };
    };
    colorCursor.ondragstart = function() {
        return false;
    };
    function getCoords(elem) {
        var box = elem.getBoundingClientRect();
        return {
            top: box.top + pageYOffset,
            left: box.left + pageXOffset
        };
    };
}
/* HSL to RGB color convert */
function HSLToRGB(h, s, l) {
    s /= 100;
    l /= 100;
    
    let c = (1 - Math.abs(2 * l - 1)) * s,
        x = c * (1 - Math.abs((h / 60) % 2 - 1)),
        m = l - c/2,
        r = 0,
        g = 0,
        b = 0;
    if (0 <= h && h < 60) {
        r = c; g = x; b = 0;  
    } else if (60 <= h && h < 120) {
        r = x; g = c; b = 0;
    } else if (120 <= h && h < 180) {
        r = 0; g = c; b = x;
    } else if (180 <= h && h < 240) {
        r = 0; g = x; b = c;
    } else if (240 <= h && h < 300) {
        r = x; g = 0; b = c;
    } else if (300 <= h && h < 360) {
        r = c; g = 0; b = x;
    }
    
    r = Math.round((r + m) * 255);
    g = Math.round((g + m) * 255);
    b = Math.round((b + m) * 255);
    
    return [r, g, b];
}
/* HSV to HSL color convert */
function HSVtoHSL(h, s, v) {
    var _h = h,
        _s = s / 100 * v / 100,
        _l = (2 - (s / 100)) * v / 100;
    _s /= (_l <= 100) ? (_l === 0 ? 100 : _l) : 200 - _l;
    _l /= 2;
    return [_h, _s * 100, _l * 100];
}
/* RGB to HSL color convert */
function RGBToHSL(r, g, b) {
    r /= 255, g /= 255, b /= 255;
    var max = Math.max(r, g, b), min = Math.min(r, g, b);
    var h, s, l = (max + min) / 2;
    if (max == min) {
        h = s = 0;
    } else {
        var d = max - min;
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
        switch (max) {
            case r: h = (g - b) / d + (g < b ? 6 : 0); break;
            case g: h = (b - r) / d + 2; break;
            case b: h = (r - g) / d + 4; break;
        }
        h /= 6;
    }
    return [parseInt(h * 360), parseInt(s * 100), parseInt(l * 100)];
}
/* HSL to HSV color convert */
function HSLtoHSV(h, s, l) {
    var _h = h,
        _s,
        _v;
    
    s = (s === 0) ? 0 : s / 100;
    l = (l === 0) ? 0 : l / 100;
    l *= 2;
    s *= (l <= 1) ? l : 2 - l;
    _v = ((l + s) === 0) ? 0 : (l + s) / 2;
    _s = ((l + s) === 0) ? 0 : (2 * s) / (l + s);
    return [_h, _s * 100, _v * 100];
}
/* RGBA to HEXA color convert */
function RGBAToHexA(r, g, b, a) {
    r = r.toString(16);
    g = g.toString(16);
    b = b.toString(16);
    a = Math.round(a * 255).toString(16);
    if (r.length == 1)
        r = "0" + r;
    if (g.length == 1)
        g = "0" + g;
    if (b.length == 1)
        b = "0" + b;
    if (a.length == 1)
        a = "0" + a;
    return "#" + r + g + b + a;
}
function HEXAToRGBA(h) {
    let r = 0, g = 0, b = 0, a = 1.0;
    if (h[0] == "#")
        h = h.slice(1, h.length);
    
    if (h.length == 3) {
        r = "0x" + h[0] + h[0];
        g = "0x" + h[1] + h[1];
        b = "0x" + h[2] + h[2];
        a = 255;
    } else if (h.length == 6) {
        r = "0x" + h[0] + h[1];
        g = "0x" + h[2] + h[3];
        b = "0x" + h[4] + h[5];
        a = 255;
    } else if (h.length == 8) {
        r = "0x" + h[0] + h[1];
        g = "0x" + h[2] + h[3];
        b = "0x" + h[4] + h[5];
        a = "0x" + h[6] + h[7];
    }
    
    return [+r, +g, +b, +a / 255];
}
/* ColorLine changer */
function colorLineChanger(movingArea, colorCursor, maxValue) {
    movingArea = document.getElementById(movingArea);
    colorCursor = document.getElementById(colorCursor);
    let pickerWidget = document.getElementById("getcolor-pickerblock__picker");
    
    movingArea.onmousedown = mouseDownEvent;
    colorCursor.onmousedown = mouseDownEvent;
    
    function mouseDownEvent(e) {
        var coords = getCoords(colorCursor);
        var shiftX = movingArea.offsetLeft - coords.left;
        
        moveAt(e);
        function moveAt(e) {
            var bounds = movingArea.getBoundingClientRect();
            var blockSizeX = parseInt(getComputedStyle(movingArea).width);
            var x = parseInt(e.clientX - bounds.left);
            
            if (x > blockSizeX)
                x = parseInt(blockSizeX);
            if (x <= 0)
                x = 0;
            
            
            colorCursor.style.left = parseInt(x - 6) + 'px';
            if (movingArea.id.split("__")[0].split("-")[1] == "huelineblock") {
                setAccentColor(Math.abs(parseInt(parseInt(x) / parseInt(blockSizeX) * maxValue)));
            } else {
                setAlphaColor(Math.abs(parseFloat(parseInt(x) / parseInt(blockSizeX)).toFixed(1)));
            }
            applyColorChanges();
        }
        document.onmousemove = function(e) {
            moveAt(e);
        };
        document.onmouseup = function() {
            document.onmousemove = null;
            document.onmouseup = null;
        };
    }
    function setAccentColor(hueValue) {
        changePickerColor(hueValue);
        changeAlphaLineColor(hueValue);
        pickerWidget.setAttribute("data-hue", hueValue);
        updateResultButtonColor();
    }
    function setAlphaColor(opacityValue) {
        pickerWidget.setAttribute("data-opacity", opacityValue);
        updateResultButtonColor();
    }
    function updateResultButtonColor() {
        let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
        let rgbaFields = document.getElementsByClassName("getcolor-rgbacodeblock__rgba");
        let rgbaValues = [parseInt(rgbaFields[0].value),
                        parseInt(rgbaFields[1].value),
                        parseInt(rgbaFields[2].value),
                        parseFloat(rgbaFields[3].value)];
        switchAndSetMainResultButtonBackground(currentState, rgbaValues);
    }
    colorCursor.ondragstart = function() {
        return false;
    };
    function getCoords(elem) {
        var box = elem.getBoundingClientRect();
        return {
            left: box.left + pageXOffset
        };
    };
}
/* Set color picker color */
function changePickerColor(hueValue) {
    document.getElementById("getcolor-pickerblock__picker").style.background
            = "linear-gradient(90deg, hsl(0, 100%, 100%) 0%, hsl("
            + hueValue + ", 100%, 50%) 100%)";
}
/* Set alpha line color */
function changeAlphaLineColor(hueValue) {
    setNewStyleElement(".getcolor-opacitylineblock__line::before",
        'background: linear-gradient(90deg, hsla(0, 100%, 100%, 0.0) 0%, hsla('
        + hueValue + ', 100%, 50%, 1.0) 100%) !important;');
}
/* Set color for result color */
function setResultColor(resultColorID, rgbaValues) {
    setNewStyleElement("#" + resultColorID, 'background: rgba('
        + rgbaValues[0] + ', ' + rgbaValues[1] + ', '
        + rgbaValues[2] + ', ' + rgbaValues[3] + ') !important;');
}
/* Set new style for element */
function setNewStyleElement(elementSelector, newSelectorRule) {
    removeElementStyle(elementSelector);
    let styleTag = document.createElement('style');
    let styleContent = document.createTextNode(elementSelector + ' { ' + newSelectorRule + ' }');
    let headTag = document.getElementsByTagName('head')[0]; 
    styleTag.appendChild(styleContent);    
    headTag.insertBefore(styleTag, headTag.childNodes[2]);
}
/* Remove element style */
function removeElementStyle(elementSelector) {
    if (document.head.getElementsByTagName("style").length > 0) {
        [].forEach.call(document.head.getElementsByTagName("style"), function(styleTag) {
            if (styleTag.textContent.includes(elementSelector)) {
                styleTag.remove();
            }
        });
    }
}
/* Set color picker cursor */
function changePickerCursor() {
    let pickerArea = document.getElementById("getcolor-pickerblock__picker");
    let pickerCursor = document.getElementById("getcolor-pickerblock__picker-cursor");
    
    let hsv = HSLtoHSV(getHueValuePicker(),
                       getSatValuePicker(),
                       getLightValuePicker());
    let cursorPosX = parseInt(hsv[1] / 100 * parseInt(getComputedStyle(pickerArea).width));
    let cursorPosY = parseInt(Math.abs(hsv[2] / 100 * parseInt(getComputedStyle(pickerArea).height) - 100));
    
    pickerCursor.style.left = parseInt(cursorPosX - 6) + 'px';
    pickerCursor.style.top = parseInt(cursorPosY - 6) + 'px';
}
/* Set hue line cursor */
function changeLinePickerCursor() {
    movingAreaSize = parseInt(getComputedStyle(document.getElementById("getcolor-huelineblock__table")).width);
    document.getElementById("getcolor-huelineblock__picker-cursor").style.left
        = parseInt(getHueValuePicker() / 360 * movingAreaSize - 4) + 'px';
    document.getElementById("getcolor-opacitylineblock__picker-cursor").style.left
        = parseInt(getAlphaValuePicker() * movingAreaSize - 4) + 'px';
}
/* Input filter function for textbox */
function setInputFilter(textbox, inputFilter) {
    ["input", "keydown", "keyup", "mousedown", "mouseup", "select", "drop"].forEach(function(event) {
      textbox.addEventListener(event, function() {
        if (inputFilter(this.value)) {
          this.oldValue = this.value;
          this.oldSelectionStart = this.selectionStart;
          this.oldSelectionEnd = this.selectionEnd;
        } else if (this.hasOwnProperty("oldValue")) {
          this.value = this.oldValue;
          this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
        } else {
          this.value = "";
        }
      });
    });
}
/* RGBA fields input filter */
[].forEach.call(document.getElementsByClassName("getcolor-rgbacodeblock__rgba"), function(colorField){
    switch(colorField.id.split("__")[1].split("_")[1]) {
        case "a":
            onCodeColorAFieldInput(colorField);
            break;
        default:
            onCodeColorRGBFieldInput(colorField);
            break;
    }
});
/* Edit field RGB function */
function onCodeColorRGBFieldInput(colorField) {
    setInputFilter(colorField, function(value) {
        if (value.length > 0)
            colorField.value = parseInt(colorField.value);
                    
        if (value > 255)
            colorField.value = 255;
        if (!isNaN(Number(colorField.value)) && colorField.value.length > 0) {
            switch(colorField.id.split("__")[0].split("-")[0]) {
                case "getcolor":
                    getColorCodeFieldsChanged();
                    break;
                default:
                    dialogColorCodeFieldsChanged(colorField.id);
                    break;
            }
        }
        
        return /^\d*$/.test(value);
    });
}
/* On RGBA code color fields changed */
function getColorCodeFieldsChanged() {
    // set hue, sat, light, alpha
    let targetInterface = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    let rgbaFields = document.getElementsByClassName("getcolor-rgbacodeblock__rgba");
    let rgbaValues = [parseInt(rgbaFields[0].value),
                      parseInt(rgbaFields[1].value),
                      parseInt(rgbaFields[2].value),
                      parseFloat(rgbaFields[3].value)];
                      
    onSetNewResultColorFromRGBA(rgbaValues);
    relatedDialogColorChange(targetInterface, rgbaValues);
    setColorToActiveLayer(targetInterface, rgbaValues);
    getActiveColorLayer().getElementsByClassName("getcolor-layerlist__field_hexa")[0].value
        = RGBAToHexA(rgbaValues[0], rgbaValues[1], rgbaValues[2], rgbaValues[3]);
}
/* Set color to layer */
function setColorToActiveLayer(targetInterface, rgbaValues) {
    var activeLayerColorButton = getActiveColorLayer().getElementsByClassName(
        "getcolor-layerlist__color")[0];
    if ((targetInterface == "normal") || (targetInterface == "hover") || (targetInterface == "pressed")) {
        setResultColor(activeLayerColorButton.id + "::before", rgbaValues);
    }
}
/* Get active layer function */
function getActiveColorLayer() {
    let activeLayer;
    [].forEach.call(document.getElementsByClassName("getcolor-layerlist__layerelement"), function(layerElement){
        if (layerElement.classList.contains("getcolor-layerlist__layerelement_active"))
            activeLayer = layerElement;
    });
    return activeLayer;
}
/* Set values to RGBA fields */
function setValuesToRgbaFields(rgbaValues) {
    let rgbaFields = document.getElementsByClassName("getcolor-rgbacodeblock__rgba");
    rgbaFields[0].value = parseInt(rgbaValues[0]);
    rgbaFields[1].value = parseInt(rgbaValues[1]);
    rgbaFields[2].value = parseInt(rgbaValues[2]);
    rgbaFields[3].value = parseFloat(rgbaValues[3]).toPrecision(2);
    getColorCodeFieldsChanged();
}
/* Send color code to related dialogs */
function relatedDialogColorChange(targetInterface, rgbaValues) {
    let rgbaFields;
    
    switch (targetInterface) {
        case "border":
            rgbaFields = document.getElementsByClassName("borderdialog-rgbacodeblock__rgba");
            break;
        case "button":
            rgbaFields = [].slice.call(document.getElementsByClassName("shadowdialog-rgbacodeblock__rgba")).slice(0, 4);
            break;
        case "text":
            rgbaFields = [].slice.call(document.getElementsByClassName("shadowdialog-rgbacodeblock__rgba")).slice(4, 8);
            break;
        default:
            return;
    }
    rgbaFields[0].value = parseInt(rgbaValues[0]);
    rgbaFields[1].value = parseInt(rgbaValues[1]);
    rgbaFields[2].value = parseInt(rgbaValues[2]);
    rgbaFields[3].value = parseFloat(rgbaValues[3]).toPrecision(2);
    dialogColorCodeFieldsChanged(rgbaFields[0].id);
}
/* On set new result color (for all lines and picker) */
function onSetNewResultColorFromRGBA(rgbaValues) {
    let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    let hsl = RGBToHSL(rgbaValues[0], rgbaValues[1], rgbaValues[2]);
    setHueValuePicker(hsl[0]);
    setSatValuePicker(hsl[1]);
    setLightValuePicker(hsl[2]);
    setAlphaValuePicker(rgbaValues[3].toPrecision(2));
    changePickerCursor();
    changeLinePickerCursor();
    changePickerColor(hsl[0]);
    changeAlphaLineColor(hsl[0]);
    setResultColor("getcolor-rgbacodeblock__resultcolor::before", rgbaValues);
    if ((currentState == "normal") || (currentState == "hover") || (currentState == "pressed")) {
        if (getCurrentStateFillswitcher("getcolor-switch") == "button") {
            var activeLayerNumber = parseInt(getActiveColorLayer().getElementsByClassName(
                "getcolor-layerlist__buttonnumber")[0].textContent);
            var activeLayerColorButton = getActiveColorLayer().getElementsByClassName(
                "getcolor-layerlist__color")[0];
            var currentIndexOfLayer = buttonInformation.getProperty(currentState, "layers").indexOf(activeLayerNumber);
            var newLayerColor = RGBAToHexA(rgbaValues[0], rgbaValues[1], rgbaValues[2], rgbaValues[3]);
            if (currentIndexOfLayer != -1) {
                buttonInformation.getProperty(currentState, "colors")[currentIndexOfLayer] = newLayerColor;
            }
            switchAndSetMainResultButtonBackground(currentState, rgbaValues);
        } else {
            buttonInformation.setProperty(currentState, "textcolor", RGBAToHexA(rgbaValues[0], 
                rgbaValues[1], rgbaValues[2], rgbaValues[3]));
            switch(currentState) {
                case "hover":
                    setResultButtonToHover();
                    break;
                case "pressed":
                    setResultButtonToPressed();
                    break;
            }
            mainResultButton.style.color = buttonInformation.getProperty(currentState, "textcolor");
            setResultButtonToNormal();
        }
    }
}
/* Switch and set background to mainResultButton */
function switchAndSetMainResultButtonBackground(currentState, rgbaValues) {
    switch(currentState) {
        case "normal":
            setResultButtonToNormal();
            setMainResultButtonBackground(currentState, rgbaValues, 0);
            break;
        case "hover":
            setResultButtonToHover();
            setMainResultButtonBackground(currentState, rgbaValues, 1);
            setResultButtonToNormal();
            break;
        case "pressed":
            setResultButtonToPressed();
            setMainResultButtonBackground(currentState, rgbaValues, 2);
            setResultButtonToNormal();
            break;
    }
}
/* Set mainResultButton background color or gradient */
function setMainResultButtonBackground(currentState, rgbaValues, buttonNumber) {
    let codeBlock = document.getElementById("getcolor-codeblock__code");
    let buttonNumberElement = document.getElementsByClassName("getcolor-gradientsblock")[0].children[buttonNumber];
    var backgroundString;
    if (buttonInformation.getProperty(currentState, "layers").length > 1)
        backgroundString = generateGradientBackgroundString(currentState);
    else
        backgroundString = "rgba(" + [rgbaValues[0], rgbaValues[1],
            rgbaValues[2], rgbaValues[3].toPrecision(2)].toString().replaceAll(",", ", ") + ")";
    mainResultButton.style.background = backgroundString;
    buttonNumberElement.style.background = backgroundString;
    buttonNumberElement.setAttribute("data-info", "background: " + backgroundString);
    codeBlock.textContent = "background: " + backgroundString;
}
/* Generate gradient background string */
function generateGradientBackgroundString(currentState) {
    var rgbaValues;
    var backgroundString = getCurrentGradientType(currentState) + "(" + getCurrentGradientAngleString(
        currentState) + ", ";
    for (var i = 0; i < buttonInformation.getProperty(currentState, "layers").length; i++) {
        rgbaValues = HEXAToRGBA(buttonInformation.getProperty(currentState, "colors")[[i]]);
        backgroundString += "rgba(" + [rgbaValues[0], rgbaValues[1],
        rgbaValues[2], rgbaValues[3].toPrecision(2)].toString().replaceAll(",", ", ") + ") "
        + buttonInformation.getProperty(currentState, "stops")[[i]] + "%, ";
    }
    
    backgroundString = backgroundString.substring(0, backgroundString.length - 2);
    backgroundString += ")";
    return backgroundString;
}
/* Get current gradient type */
function getCurrentGradientType(currentState) {
    return buttonInformation.getProperty(currentState, "gradienttype");
}
/* Get current gradient angle */
function getCurrentGradientAngleString(currentState) {
    if (getCurrentGradientType(currentState) == "linear-gradient")
        return buttonInformation.getProperty(currentState, "angle") + "deg";
    else
        return "circle";
}
/* Edit field A function */
function onCodeColorAFieldInput(colorField) {
    setInputFilter(colorField, function(value) {
        if (parseFloat(value) > parseFloat(1.0))
            colorField.value = '1.0';
        if (!isNaN(Number(colorField.value)) && colorField.value.length > 0) {
            switch(colorField.id.split("__")[0].split("-")[0]) {
                case "getcolor":
                    getColorCodeFieldsChanged();
                    break;
                default:
                    dialogColorCodeFieldsChanged(colorField.id);
                    break;
            }
        }
        
        return /^[10]?\.?\d*$/.test(value);
    });
}
/* On switch button clicked */
["click", "touchend"].forEach(function(eventType){
    [].forEach.call(document.getElementsByClassName("om-switch__element"), function(switchButton) {
        switchButton.addEventListener(eventType, function(){
            colorDestinationSwitchClicked(switchButton.id);
        });
    });
});
/* Color destination switcher */
function colorDestinationSwitchClicked(buttonID) {
    let clickedButton = document.getElementById(buttonID);
    let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    let tabsSection = document.getElementsByClassName("getcolor-tabssection")[0];
    [].forEach.call(clickedButton.parentElement.getElementsByClassName("om-switch__element"),
    function(switchButton){
        if (switchButton == clickedButton) {
            if (!switchButton.classList.contains("om-switch__element_active")) {
                switchButton.classList.add("om-switch__element_active");
            }
        } else {
            if (switchButton.classList.contains("om-switch__element_active")) {
                switchButton.classList.remove("om-switch__element_active");
            }
        }
        if ((getCurrentStateFillswitcher("getcolor-switch") == "text") &&
            (!tabsSection.classList.contains("unvisible"))) {
            tabsSection.classList.add("unvisible");
            setValuesToRgbaFields(HEXAToRGBA(buttonInformation.getProperty(currentState, "textcolor")));
        } else if ((getCurrentStateFillswitcher("getcolor-switch") == "button") &&
                   (tabsSection.classList.contains("unvisible"))) {
            tabsSection.classList.remove("unvisible");
            updateSettingsColorDialog(currentState, "getcolor-interface__window");
        }
    });
}
/* Apply color changes from cursor widgets */
function applyColorChanges() {
    let targetInterface = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    let rgb = HSLToRGB(parseInt(getHueValuePicker()),
                       parseInt(getSatValuePicker()),
                       parseInt(getLightValuePicker()));
    let rgbaFields = document.getElementsByClassName("getcolor-rgbacodeblock__rgba");
    let rgbaValues = [rgb[0], rgb[1], rgb[2], getAlphaValuePicker().toPrecision(2)];
    rgbaFields[0].value = rgbaValues[0];
    rgbaFields[1].value = rgbaValues[1];
    rgbaFields[2].value = rgbaValues[2];
    rgbaFields[3].value = rgbaValues[3];
    setResultColor("getcolor-rgbacodeblock__resultcolor::before", [rgbaFields[0].value,
        rgbaFields[1].value, rgbaFields[2].value, rgbaFields[3].value]);
    getActiveColorLayer().getElementsByClassName("getcolor-layerlist__field_hexa")[0].value
        = RGBAToHexA(rgbaValues[0], rgbaValues[1], rgbaValues[2], rgbaValues[3]);
    
    relatedDialogColorChange(targetInterface, rgbaValues);
    setColorToActiveLayer(targetInterface, rgbaValues);
    
    if ((targetInterface == "normal") || (targetInterface == "hover") || (targetInterface == "pressed")) {
        if (getCurrentStateFillswitcher("getcolor-switch") == "button") {
            var activeLayerNumber = parseInt(getActiveColorLayer().getElementsByClassName(
                "getcolor-layerlist__buttonnumber")[0].textContent);
            var currentIndexOfLayer = buttonInformation.getProperty(targetInterface, "layers").indexOf(activeLayerNumber);
            var newLayerColor = RGBAToHexA(rgbaValues[0], rgbaValues[1], rgbaValues[2], rgbaValues[3]);
            if (currentIndexOfLayer != -1) {
                buttonInformation.getProperty(targetInterface, "colors")[currentIndexOfLayer] = newLayerColor;
            }
        } else {
            buttonInformation.setProperty(targetInterface, "textcolor", RGBAToHexA(rgbaValues[0], rgbaValues[1],
                rgbaValues[2], rgbaValues[3]));
            switch(currentState) {
                case "hover":
                    setResultButtonToHover();
                    break;
                case "pressed":
                    setResultButtonToPressed();
                    break;
            }
            mainResultButton.style.color = buttonInformation.getProperty(currentState, "textcolor");
            setResultButtonToNormal();
        }
    }
}
/* Return hue value picker block */
function getHueValuePicker() {
    return parseInt(document.getElementById("getcolor-pickerblock__picker").getAttribute("data-hue"));
}
/* Set hue value picker block */
function setHueValuePicker(hueValue) {
    document.getElementById("getcolor-pickerblock__picker").setAttribute("data-hue", hueValue);
}
/* Return sat value picker block */
function getSatValuePicker() {
    return parseInt(document.getElementById("getcolor-pickerblock__picker").getAttribute("data-sat"));
}
/* Set sat value picker block */
function setSatValuePicker(satValue) {
    document.getElementById("getcolor-pickerblock__picker").setAttribute("data-sat", satValue);
}
/* Return light value picker block */
function getLightValuePicker() {
    return parseInt(document.getElementById("getcolor-pickerblock__picker").getAttribute("data-light"));
}
/* Set light value picker block */
function setLightValuePicker(lightValue) {
    document.getElementById("getcolor-pickerblock__picker").setAttribute("data-light", lightValue);
}
/* Return alpha value picker block */
function getAlphaValuePicker() {
    return parseFloat(document.getElementById("getcolor-pickerblock__picker").getAttribute("data-opacity"));
}
/* Set alpha value picker block */
function setAlphaValuePicker(alphaValue) {
    document.getElementById("getcolor-pickerblock__picker").setAttribute("data-opacity", alphaValue);
}
/* Enable color cursors */
moveColorCursor("getcolor-pickerblock__picker-cursor", "getcolor-pickerblock__picker");
colorLineChanger("getcolor-huelineblock__table", "getcolor-huelineblock__picker-cursor", 359);
colorLineChanger("getcolor-opacitylineblock__table", "getcolor-opacitylineblock__picker-cursor", 100);
//////////////////////////////////////////////////////////////////////////////////////////////////////
/* Button handlers */
["click", "touchend"].forEach(function(eventType){
    /* Create new layer button handler */
    document.getElementById("getcolor-layerlist__listbutton_addlayer").addEventListener(eventType, () => {
        createNewLayer(document.getElementsByClassName("getcolor-layerlist")[0]);
    });
    /* Remove layer button handler */
    document.getElementById("getcolor-layerlist__listbutton_removelayer").addEventListener(eventType, () => {
        removeLayer(document.getElementsByClassName("getcolor-layerlist")[0]);
    });
    /* Layer number button handler */
    [].forEach.call(document.getElementsByClassName("getcolor-layerlist__buttonnumber"), function(buttonNumber){
        buttonNumber.addEventListener(eventType, () => setActiveLayer(buttonNumber));
    });
    /* Layer remove button clicked */
    [].forEach.call(document.getElementsByClassName("getcolor-layerlist__removebutton"), function(removeButton){
        removeButton.addEventListener(eventType, () => removeThisLayer(removeButton));
    });
});
/* Set active layer */
function setActiveLayer(buttonNumber) {
    let layerSection = buttonNumber.parentElement.parentElement;
    let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    let colorLayers = layerSection.getElementsByClassName("getcolor-layerlist__layerelement");
    let currentNumberOfLayer = buttonNumber.textContent;
    if (layerSection.childElementCount > 1) {
        [].forEach.call(colorLayers, function(colorLayer){
            let colorLayerButtonNumber = colorLayer.getElementsByClassName("getcolor-layerlist__buttonnumber")[0];
            if (colorLayerButtonNumber.textContent == currentNumberOfLayer) {
                if (!colorLayerButtonNumber.classList.contains("getcolor-layerlist__buttonnumber_active")) {
                    colorLayerButtonNumber.classList.toggle("getcolor-layerlist__buttonnumber_active");
                    colorLayerButtonNumber.parentElement.classList.toggle("getcolor-layerlist__layerelement_active");
                    var colorButton = colorLayer.getElementsByClassName("getcolor-layerlist__color")[0];
                    //var rgbaValues = getComputedStyle(colorButton).getPropertyValue("background-color");
                    var rgbaValues = HEXAToRGBA(buttonInformation.getProperty(currentState, "colors")[
                        buttonInformation.getProperty(currentState, "layers").indexOf(parseInt(
                            colorLayerButtonNumber.textContent))]);
                    let rgbaFields = document.getElementsByClassName("getcolor-rgbacodeblock__rgba");
                    
                    rgbaFields[0].value = parseInt(rgbaValues[0]);
                    rgbaFields[1].value = parseInt(rgbaValues[1]);
                    rgbaFields[2].value = parseInt(rgbaValues[2]);
                    rgbaFields[3].value = parseFloat(rgbaValues[3]).toPrecision(2);
                    let hsl = RGBToHSL(rgbaFields[0].value, rgbaFields[1].value, rgbaFields[2].value);
                    setNewStyleElement("#getcolor-rgbacodeblock__resultcolor::before", 'background: rgba('
                        + rgbaValues[0] + ', ' + rgbaValues[1] + ', '
                        + rgbaValues[2] + ', ' + rgbaValues[3] + ') !important;');
                    setHueValuePicker(hsl[0]);
                    setSatValuePicker(hsl[1]);
                    setLightValuePicker(hsl[2]);
                    setAlphaValuePicker(rgbaValues[3].toPrecision(2));
                    changePickerCursor();
                    changePickerColor(hsl[0]);
                    changeAlphaLineColor(hsl[0]);
                }
            } else {
                if (colorLayerButtonNumber.classList.contains("getcolor-layerlist__buttonnumber_active")) {
                    colorLayerButtonNumber.classList.toggle("getcolor-layerlist__buttonnumber_active");
                    colorLayerButtonNumber.parentElement.classList.toggle("getcolor-layerlist__layerelement_active");
                }
            }
        });
    }
}
/* Return text of current state fillswitcher by ID */
function getCurrentStateFillswitcher(fillswitcherID) {
    let fillSwitcher = document.getElementById(fillswitcherID);
    var currentState;
    [].forEach.call(document.getElementsByClassName("om-switch__element"), (fillSwitcherButton) => {
        if (fillSwitcherButton.classList.contains("om-switch__element_active")) {
            currentState = fillSwitcherButton.id.split("__")[1].split("_")[1];
        }
    });
    return currentState;
}
/* Add new layer */
function createNewLayer(layersSection, newLayerNumber="", newLayerColor="", newLayerStop="") {
    let countOfLayers = layersSection.childElementCount;
    let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    
    let layerElement = document.createElement('div');
    layerElement.classList.add("getcolor-layerlist__layerelement");
    
    if (newLayerNumber == "") {
        newLayerNumber = countOfLayers;
        while (document.getElementById("getcolor-layerlist__color_" + newLayerNumber) != null) {
            newLayerNumber++;
        }
    }
    if (newLayerColor == "") {
        newLayerColor = "#FFDDEE64";
    }
    if (newLayerStop == "") {
        newLayerStop = 0;
    }
    layerElement.innerHTML = '<div class="om-button om-button__text getcolor-layerlist__buttonnumber">'
    + (newLayerNumber) + '</div> \
                        <div class="getcolor-layerlist__color" \
                            id="getcolor-layerlist__color_' + (newLayerNumber) + '"></div> \
                        <span class="getcolor-layerlist__prefix getcolor-layerlist__prefix_hexa">Hexa: \
                            <input type="text" \
                                class="getcolor-layerlist__field getcolor-layerlist__field_hexa" \
                                maxlength="9" \
                                value="' + newLayerColor + '"> \
                        </span> \
                        <span class="getcolor-layerlist__prefix getcolor-layerlist__prefix_stop">Стоп: \
                            <input type="text" \
                                class="getcolor-layerlist__field getcolor-layerlist__field_stop" \
                                maxlength="3" \
                                value="' + newLayerStop +'"> \
                        </span> \
                        <div class="om-button om-button__text getcolor-layerlist__removebutton"> \
                            <i class="fas fa-times"></i> \
                        </div>';
    layersSection.appendChild(layerElement);
    let layerElementButtonNumber = layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0];
    let layerElementButtonRemove = layerElement.getElementsByClassName("getcolor-layerlist__removebutton")[0];
    ["click", "touchend"].forEach(function(eventType){
        layerElementButtonNumber.addEventListener(eventType, () => setActiveLayer(
            layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0]));
        layerElementButtonRemove.addEventListener(eventType, () => removeThisLayer(layerElementButtonRemove));
    });
    setInputFilter(layerElement.getElementsByClassName("getcolor-layerlist__field_hexa")[0], function(value) {
        return /^#[\dabcdefABCDEF]*$/.test(value);
    });
    setInputFilter(layerElement.getElementsByClassName("getcolor-layerlist__field_stop")[0], function(value) {
        var stopField = layerElement.getElementsByClassName("getcolor-layerlist__field_stop")[0];
        var currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
        let currentLayerNumber = parseInt(stopField.parentElement.parentElement.getElementsByClassName(
            "getcolor-layerlist__buttonnumber")[0].textContent);
        if (value == "") {
            stopField.value = 0;
        }
        
        if (value.length > 0)
            stopField.value = parseInt(stopField.value);
                    
        if (value < 0)
            stopField.value = 0;
        else if (value > 100)
            stopField.value = 100;
        
        var rgbaValues;
        
        for (var i = 0; i < buttonInformation.getProperty("normal", "layers").length; i++) {
            if (buttonInformation.getProperty("normal", "layers")[i] == currentLayerNumber) {
                buttonInformation.getProperty(currentState, "stops")[i] = stopField.value;
                rgbaValues = HEXAToRGBA(buttonInformation.getProperty(currentState, "colors")[i]);
            }
        }
        switchAndSetMainResultButtonBackground(currentState, rgbaValues);
        
        return /^\d*$/.test(value);
    });
    setNewStyleElement("#getcolor-layerlist__color_" + newLayerNumber + "::before",
        "background: " + newLayerColor);
    
    var currentIndexOfLayer = buttonInformation.getProperty(currentState, "layers").indexOf(newLayerNumber);
    if (currentIndexOfLayer != -1) {
        buttonInformation.getProperty(currentState, "layers")[currentIndexOfLayer] = newLayerNumber;
        buttonInformation.getProperty(currentState, "colors")[currentIndexOfLayer] = newLayerColor;
        buttonInformation.getProperty(currentState, "stops")[currentIndexOfLayer] = newLayerStop;
    } else {
        buttonInformation.getProperty(currentState, "layers").push(newLayerNumber);
        buttonInformation.getProperty(currentState, "colors").push(newLayerColor);
        buttonInformation.getProperty(currentState, "stops").push(newLayerStop);
    }
}
/* Remove layer */
function removeLayer(layersSection) {
    let deletedNumber;
    if (layersSection.getElementsByClassName("getcolor-layerlist__layerelement").length > 1) {
        [].forEach.call(layersSection.getElementsByClassName("getcolor-layerlist__layerelement"), function(layerElement){
            if (layerElement.classList.contains("getcolor-layerlist__layerelement_active")) {
                deletedNumber = parseInt(layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0].textContent);
                removeElementStyle(layerElement.getElementsByClassName("getcolor-layerlist__color")[0].id + "::before");
                layersSection.removeChild(layerElement);
                var currentIndexOfLayer = buttonInformation.getProperty(currentState, "layers").indexOf(deletedNumber);
                if (currentIndexOfLayer != -1) {
                    buttonInformation.getProperty(currentState, "layers").splice(currentIndexOfLayer, 1);
                    buttonInformation.getProperty(currentState, "colors").splice(currentIndexOfLayer, 1);
                    buttonInformation.getProperty(currentState, "stops").splice(currentIndexOfLayer, 1);
                }
            }
        });
        layersSection.getElementsByClassName("getcolor-layerlist__layerelement")[0].classList.toggle("getcolor-layerlist__layerelement_active");
        layersSection.getElementsByClassName("getcolor-layerlist__layerelement")[0].getElementsByClassName("getcolor-layerlist__buttonnumber")[0].classList.toggle(
            "getcolor-layerlist__buttonnumber_active");
    }
    switchAndSetMainResultButtonBackground(currentState, rgbaValues);
}
/* On remove button at layer clicked */
function removeThisLayer(buttonElement) {
    let currentLayerElement = buttonElement.parentElement;
    let layersSection = currentLayerElement.parentElement;
    let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    let deletedNumber;
    
    if (layersSection.getElementsByClassName("getcolor-layerlist__layerelement").length > 1) {
        deletedNumber = parseInt(currentLayerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0].textContent);
        removeElementStyle(currentLayerElement.getElementsByClassName("getcolor-layerlist__color")[0].id + "::before");
        layersSection.removeChild(currentLayerElement);
        
        var currentIndexOfLayer = buttonInformation.getProperty(currentState, "layers").indexOf(deletedNumber);
        if (currentIndexOfLayer != -1) {
            buttonInformation.getProperty(currentState, "layers").splice(currentIndexOfLayer, 1);
            buttonInformation.getProperty(currentState, "colors").splice(currentIndexOfLayer, 1);
            buttonInformation.getProperty(currentState, "stops").splice(currentIndexOfLayer, 1);
        }
        if (currentLayerElement.classList.contains("getcolor-layerlist__layerelement_active")) {
            layersSection.getElementsByClassName("getcolor-layerlist__layerelement")[0].classList.toggle("getcolor-layerlist__layerelement_active");
            layersSection.getElementsByClassName("getcolor-layerlist__layerelement")[0].getElementsByClassName("getcolor-layerlist__buttonnumber")[0].classList.toggle(
                "getcolor-layerlist__buttonnumber_active");
        }
    }
    switchAndSetMainResultButtonBackground(currentState, rgbaValues);
}
/* Set settings by currentState */
function updateSettingsColorDialog(currentState, callWindow) {
    document.getElementById("getcolor-tabssection__tab_layers").click();
    document.getElementById("getcolor-tabssection__tab_color").click();
    
    let colorDialogWindowTabsSection = document.getElementsByClassName("getcolor-tabssection")[0];
    let rgbaFields = document.getElementsByClassName("getcolor-rgbacodeblock__rgba");
    let rgbaValues;
    switch(currentState){
        case "border":
            rgbaValues = HEXAToRGBA(buttonInformation.getProperty(
                callWindow.getAttribute("data-info"), "bordercolor"));
            if (!colorDialogWindowTabsSection.classList.contains("unvisible"))
                colorDialogWindowTabsSection.classList.add("unvisible");
            break;
        case "button":
            rgbaValues = HEXAToRGBA(buttonInformation.getProperty(
                callWindow.getAttribute("data-info"), "boxshadowcolor"));
            if (!colorDialogWindowTabsSection.classList.contains("unvisible"))
                colorDialogWindowTabsSection.classList.add("unvisible");
            break;
        case "text":
            rgbaValues = HEXAToRGBA(buttonInformation.getProperty(
                callWindow.getAttribute("data-info"), "textshadowcolor"));
            if (!colorDialogWindowTabsSection.classList.contains("unvisible"))
                colorDialogWindowTabsSection.classList.add("unvisible");
            break;
        default:
            rgbaValues = HEXAToRGBA(buttonInformation.getProperty(currentState, "colors")[0]);
            document.getElementById("getcolor-switch__element_button").click();
            if (colorDialogWindowTabsSection.classList.contains("unvisible"))
                colorDialogWindowTabsSection.classList.remove("unvisible");
            break;
    }
    
    rgbaFields[0].value = rgbaValues[0];
    rgbaFields[1].value = rgbaValues[1];
    rgbaFields[2].value = rgbaValues[2];
    rgbaFields[3].value = rgbaValues[3].toPrecision(2);
    resetLayers();
    setLayersFromButtonInfo(currentState);
    getColorCodeFieldsChanged();
}
/* Set colors and count from button info for normal, hover and pressed states */
function setLayersFromButtonInfo(currentState) {
    if ((currentState == "normal") || (currentState == "hover") || (currentState == "pressed")) {
        // Нужно собрать количество слоев-проходок, установить цвет для каждого слоя
        // При вызове функции всегда есть только один слой, нужно создавать слои после
        // Все стили после resetLayers() отсутствуют, их нужно все заливать
        // layers из buttonInformation выводит массив с номерами слоев
        // layers.length - количество слоев
        let layerSection = document.getElementsByClassName("getcolor-layerlist")[0];
        let layerElement = layerSection.getElementsByClassName("getcolor-layerlist__layerelement")[0];
        let colorElement = layerElement.getElementsByClassName("getcolor-layerlist__color")[0];
        
        if (getCurrentStateFillswitcher("getcolor-switch") == "button") {
            layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0].textContent
                = buttonInformation.getProperty(currentState, "layers")[0];
            colorElement.id = colorElement.id.replace(/.$/g, buttonInformation.getProperty(currentState, "layers")[0]);
            setNewStyleElement("#" + colorElement.id + "::before", "background: "
                + buttonInformation.getProperty(currentState,
                "colors")[0]);
            for (var i = 1; i < buttonInformation.getProperty(currentState, "layers").length; i++) {
                createNewLayer(document.getElementsByClassName("getcolor-layerlist")[0],
                    buttonInformation.getProperty(currentState, "layers")[i],
                    buttonInformation.getProperty(currentState, "colors")[i],
                    buttonInformation.getProperty(currentState, "stops")[i]);
            }
        } else {
            layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0].textContent
                = 1;
            colorElement.id = colorElement.id.replace(/.$/g, 1);
        }
    }
}
/* Removes all layers and create one layer */
function resetLayers() {
    let layerSection = document.getElementsByClassName("getcolor-layerlist")[0];
    let countOfLayers = layerSection.childElementCount;
    if (countOfLayers > 1) {
        [].forEach.call(layerSection.getElementsByClassName("getcolor-layerlist__layerelement"),
            function(layerElement){
                layerNumberElement = layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0];
                layerNumber = parseInt(layerNumberElement.textContent);
                removeElementStyle("getcolor-layerlist__color_" + layerNumber + "::before");
        });
        
        while (layerSection.getElementsByClassName("getcolor-layerlist__layerelement").length > 0) {
            layerSection.getElementsByClassName("getcolor-layerlist__layerelement")[0].remove();
        }
        layerElement = document.createElement('div');
        layerElement.classList.add("getcolor-layerlist__layerelement");
        layerElement.classList.add("getcolor-layerlist__layerelement_active");
        layerElement.innerHTML = '<div class="om-button om-button__text getcolor-layerlist__buttonnumber \
                            getcolor-layerlist__buttonnumber_active">1</div> \
                            <div class="getcolor-layerlist__color" \
                                id="getcolor-layerlist__color_1"></div> \
                            <span class="getcolor-layerlist__prefix getcolor-layerlist__prefix_hexa">Hexa: \
                                <input type="text" \
                                    class="getcolor-layerlist__field getcolor-layerlist__field_hexa" \
                                    maxlength="9" \
                                    value="#FFDDEE64"> \
                            </span> \
                            <span class="getcolor-layerlist__prefix getcolor-layerlist__prefix_stop">Стоп: \
                                <input type="text" \
                                    class="getcolor-layerlist__field getcolor-layerlist__field_stop" \
                                    maxlength="3" \
                                    value="0"> \
                            </span> \
                            <div class="om-button om-button__text getcolor-layerlist__removebutton"> \
                                <i class="fas fa-times"></i> \
                            </div>';
        layerSection.appendChild(layerElement);
        let layerElementButtonNumber = layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0];
        let layerElementButtonRemove = layerElement.getElementsByClassName("getcolor-layerlist__removebutton")[0];
        ["click", "touchend"].forEach(function(eventType){
            layerElementButtonNumber.addEventListener(eventType, () => setActiveLayer(
                layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0]));
            layerElementButtonRemove.addEventListener(eventType, () => removeThisLayer(layerElementButtonRemove));
        });
        
        setInputFilter(layerElement.getElementsByClassName("getcolor-layerlist__field_hexa")[0], function(value) {
            return /^#[\dabcdefABCDEF]*$/.test(value);
        });
        setInputFilter(layerElement.getElementsByClassName("getcolor-layerlist__field_stop")[0], function(value) {
            var stopField = layerElement.getElementsByClassName("getcolor-layerlist__field_stop")[0];
            let currentLayerNumber = parseInt(stopField.parentElement.parentElement.getElementsByClassName(
                "getcolor-layerlist__buttonnumber")[0].textContent);
            if (value == "") {
                stopField.value = 0;
            }
            if (value.length > 0)
                stopField.value = parseInt(stopField.value);
                        
            if (value < 0)
                stopField.value = 0;
            else if (value > 100)
                stopField.value = 100;
            
            var rgbaValues;
        
            for (var i = 0; i < buttonInformation.getProperty("normal", "layers").length; i++) {
                if (buttonInformation.getProperty("normal", "layers")[i] == currentLayerNumber) {
                    buttonInformation.getProperty(currentState, "stops")[i] = stopField.value;
                    rgbaValues = HEXAToRGBA(buttonInformation.getProperty(currentState, "colors")[i]);
                }
            }
            switchAndSetMainResultButtonBackground(currentState, rgbaValues);
            
            return /^\d*$/.test(value);
        });
    } else {
        layerElement = layerSection.getElementsByClassName("getcolor-layerlist__layerelement")[0];
        layerNumberElement = layerElement.getElementsByClassName("getcolor-layerlist__buttonnumber")[0];
        layerNumber = parseInt(layerNumberElement.textContent);
        if (layerNumber != 1) {
            layerNumberElement.textContent = 1;
            colorElement = layerElement.getElementsByClassName("getcolor-layerlist__color")[0];
            colorElement.id = colorElement.id.replace(/.$/g, "1");
        } else {
            setInputFilter(layerElement.getElementsByClassName("getcolor-layerlist__field_hexa")[0], function(value) {
                return /^#[\dabcdefABCDEF]*$/.test(value);
            });
            setInputFilter(layerElement.getElementsByClassName("getcolor-layerlist__field_stop")[0], function(value) {
                var stopField = layerElement.getElementsByClassName("getcolor-layerlist__field_stop")[0];
                let currentLayerNumber = parseInt(stopField.parentElement.parentElement.getElementsByClassName(
                    "getcolor-layerlist__buttonnumber")[0].textContent);
                if (value == "") {
                    stopField.value = 0;
                }
                
                if (value.length > 0)
                    stopField.value = parseInt(stopField.value);
                            
                if (value < 0)
                    stopField.value = 0;
                else if (value > 100)
                    stopField.value = 100;
                
                var rgbaValues;
        
                for (var i = 0; i < buttonInformation.getProperty("normal", "layers").length; i++) {
                    if (buttonInformation.getProperty("normal", "layers")[i] == currentLayerNumber) {
                        buttonInformation.getProperty(currentState, "stops")[i] = stopField.value;
                        rgbaValues = HEXAToRGBA(buttonInformation.getProperty(currentState, "colors")[i]);
                    }
                }
                
                switchAndSetMainResultButtonBackground(currentState, rgbaValues);
                
                return /^\d*$/.test(value);
            });
        }
        removeElementStyle("getcolor-layerlist__color_" + layerNumber + "::before");
    }
}
/* Update mainResultButton color settings by current state */
function updateMainResultButtonColorSettings(currentState) {
    var rgbaValues = HEXAToRGBA(buttonInformation.getProperty(currentState, "colors")[0]);
    switchAndSetMainResultButtonBackground(currentState, rgbaValues);
    if (document.getElementById("getcolor-tabssection__tab_gradient").classList.contains(
        "getcolor-tabssection__tab_active"))
        highlightCssCode("getcolor");
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
let buttonGradientRadial = document.getElementById("getcolor-gradientsettings__buttonradial");
let buttonGradientLinear = document.getElementById("getcolor-gradientsettings__buttonlinear");
/* Filling data-info attribute for buttons gradient template */
["click", "touchend"].forEach(function(eventType){
    /* On button radial gradient clicked */
    buttonGradientRadial.addEventListener(eventType, function() {
        let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
        buttonInformation.setProperty(currentState, "gradienttype", "linear-gradient");
        updateMainResultButtonColorSettings(currentState);
    });
    /* On button linear gradient clicked */
    buttonGradientLinear.addEventListener(eventType, function() {
        let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
        buttonInformation.setProperty(currentState, "gradienttype", "radial-gradient");
        updateMainResultButtonColorSettings(currentState);
    });
    /* Library gradient click handler and fill data-info attribute */
    [].forEach.call(document.getElementsByClassName("getcolor-gradientsblock")[0].children, (libraryButton) => {
        if (getComputedStyle(libraryButton).backgroundImage != "none") {
            libraryButton.setAttribute("data-info", "background: " + getComputedStyle(
                libraryButton).backgroundImage);
        } else {
            libraryButton.setAttribute("data-info", "background: " + getComputedStyle(
                libraryButton).backgroundColor);
        }
        libraryButton.addEventListener(eventType, (e) => {
            onButtonGradientLibClicked(e.target);
        });
    });
});
/* On button gradient template clicked */
function onButtonGradientLibClicked(libraryButton) {
    let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    if (libraryButton.getAttribute("data-info")) {
        var backgroundString = parseBackgroundString(libraryButton.getAttribute("data-info"));
        let rgbaFields = document.getElementsByClassName("getcolor-rgbacodeblock__rgba");
        var rgbaValues;
        var backgroundLayers = 1;
        if (backgroundString.length > 4) {
            buttonInformation.setProperty(currentState, "layers", new Array());
            buttonInformation.setProperty(currentState, "colors", new Array());
            buttonInformation.setProperty(currentState, "stops", new Array());
            buttonInformation.setProperty(currentState, "angle", parseInt(backgroundString[1].replace("deg", "")));
            degreeField.value = buttonInformation.getProperty(currentState, "angle");
            for (var i = 0; i < (backgroundString.length - 2) / 2; i++) {
                buttonInformation.getProperty(currentState, "layers").push(i+1);
                buttonInformation.getProperty(currentState, "colors").push(RGBAToHexA(backgroundString[i*2+2][0],
                    backgroundString[i*2+2][1], backgroundString[i*2+2][2], backgroundString[i*2+2][3]));
                buttonInformation.getProperty(currentState, "stops").push(backgroundString[i*2+3]);
            }
        } else {
            buttonInformation.setProperty(currentState, "layers", [1]);
            buttonInformation.setProperty(currentState, "colors", [RGBAToHexA(backgroundString[0],
                backgroundString[1], backgroundString[2], backgroundString[3]
            )]);
            buttonInformation.setProperty(currentState, "stops", [0]);
        }
        rgbaValues = HEXAToRGBA(buttonInformation.getProperty(currentState, "colors")[0]);
        rgbaFields[0].value = rgbaValues[0];
        rgbaFields[1].value = rgbaValues[1];
        rgbaFields[2].value = rgbaValues[2];
        rgbaFields[3].value = rgbaValues[3].toPrecision(2);
        resetLayers();
        setLayersFromButtonInfo(currentState);
        getColorCodeFieldsChanged();
        if (document.getElementById("getcolor-tabssection__tab_gradient").classList.contains(
            "getcolor-tabssection__tab_active"))
            highlightCssCode("getcolor");
    }
}
let degreeField = document.getElementById("getcolor-gradientsettings__field_degree");
/* Edit degree field function */
setInputFilter(degreeField, function(value) {
    let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    if (value == "")
        degreeField.value = 0;
    if (value.length > 0)
        degreeField.value = parseInt(degreeField.value);
                
    if (value < 0)
        degreeField.value = 0;
    else if (value > 360)
        degreeField.value = 360;
    buttonInformation.setProperty(currentState, "angle", degreeField.value);
    updateMainResultButtonColorSettings(currentState);
    
    return /^\d*$/.test(value);
});
/* Rotate degree buttons handlers */
["click", "touchend"].forEach(function(eventType){
    // Rotate left button
    document.getElementById("getcolor-gradientsettings__button_rotateleft").addEventListener(eventType, () => {
        let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
        if (degreeField.value > 15)
            degreeField.value = parseInt(degreeField.value) - 15;
        else
            degreeField.value = 0;
        buttonInformation.setProperty(currentState, "angle", degreeField.value);
        updateMainResultButtonColorSettings(currentState);
    });
    // Rotate right button
    document.getElementById("getcolor-gradientsettings__button_rotateright").addEventListener(eventType, () => {
        let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
        if (degreeField.value < 345)
            degreeField.value = parseInt(degreeField.value) + 15;
        else
            degreeField.value = 360;
        buttonInformation.setProperty(currentState, "angle", degreeField.value);
        updateMainResultButtonColorSettings(currentState);
    });
});
/* Parse background string returns color array or gradient color array */
function parseBackgroundString(backgroundString) {
    if (backgroundString.match("background: rgba")) {
        return parseRGBAString(backgroundString);
    } else {
        var backgroundGradientArray = new Array();
        var rgbaStrings = new Array();
        var colorArray = backgroundString.replace(/ +/g, '').match(/(rgba?)\(\d+,\d+,\d+\,?\d+?\.?\d?\d?\)\d+\%?/g);
        backgroundGradientArray.push(backgroundString.replace(/ +/g, '').match(/(\w+-gradient)/g)[0]); // Gradient type
        backgroundGradientArray.push(backgroundString.replace(/ +/g, "").split(backgroundGradientArray[0] + "(")[1].split(",")[0]); // Gradient property
        for (var i = 0; i < colorArray.length; i++) {
            rgbaStrings.push(parseRGBAString(colorArray[i].split(")")[0] + ")"));
            backgroundGradientArray.push(rgbaStrings[i]);
            backgroundGradientArray.push(parseInt(colorArray[i].split(")")[1].split("%")[0]));
        }
        return backgroundGradientArray;
    }
}
/* Parse colors from rgba(x, x, x, x.x) string */
function parseRGBAString(rgbaString){
    var parsedArray = rgbaString.replace(/ +/g, '').match(/(rgba?)|(\d+(\.\d+)?%?)|(\.\d+)/g);
    var colorArray = new Array();
    
    if (!parsedArray)
        return null;
    
    if (parsedArray[0] == "rgba" && parsedArray.length == 5) {
        for(var i = 1; i < 5; i++) {
            if (i != 4)
                colorArray.push(parseInt(parsedArray[i]));
            else
                colorArray.push(parseFloat(parsedArray[i]));
        }
    } else if (parsedArray[0] == "rgb" && parsedArray.length == 4) {
        for(var i = 1; i < 4; i++)
            colorArray.push(parseInt(parsedArray[i]));
        colorArray.push(1.0);
    } else
        return null;
    return colorArray;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
/**** Code block ****/
/* Copy button handler */
["click", "touchend"].forEach(function(eventType){
    document.getElementsByClassName("getcolor-codeblock__copy")[0].addEventListener(eventType, function(e){
        copyCodeButtonClicked(e.target);
    });
});
/* Display line numbers in code block */
function displayLineNumbers(interfaceName, prefix="") {
    if (prefix != "")
        if (prefix[0] != "_")
            prefix = "_" + prefix;
    let codeAreaWidget = document.getElementById(interfaceName + "-codeblock__codearea" + prefix);
    let codeBlock = codeAreaWidget.getElementsByClassName(interfaceName + "-codeblock__code")[0];
    let codeLineNumbers = codeAreaWidget.getElementsByClassName(interfaceName + "-codeblock__linenumbers")[0];
    let textColumnSize = codeBlock.clientWidth / parseInt(getTextWidth(
        window.getComputedStyle(codeBlock).getPropertyValue("font-family")
    ));
    codeLineNumbers.textContent = "1";
    if (codeBlock.textContent.includes('\n')) {
        for (i = 0; i < Math.ceil(codeBlock.textContent.split("\n").length) - 1; i++) {
            for (j = 0; j < (Math.ceil(codeBlock.textContent.split("\n")[i].length - 7) / textColumnSize); j++) {
                codeLineNumbers.textContent += "\n";
            }
            if (codeLineNumbers.textContent[codeLineNumbers.textContent.length - 1] == "\n")
                codeLineNumbers.textContent += (i + 2);
            else
                codeLineNumbers.textContent += "\n" + (i + 2);
        }
    }
}
/* Highlight some css code */
function highlightCssCode(interfaceName, prefix="", codeLanguage="css") {
    // const regex2 = new RegExp('\\w+');
    if (prefix != "")
        if (prefix[0] != "_")
            prefix = "_" + prefix;
    let codeAreaWidget = document.getElementById(interfaceName + "-codeblock__codearea" + prefix);
    let codeBlock = codeAreaWidget.getElementsByClassName(interfaceName + "-codeblock__code")[0];
    if (codeBlock.textContent.match(/(.+): /g) !== null) {
        codeBlock.innerHTML = codeBlock.textContent.replace(/(.+): /g, '<span style="color:cyan;">$&</span>');
    }
}
/* Get width of symbol */
function getTextWidth(font) {
    var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText("W");
    return metrics.width;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
/* Add tab buttons handler */
["click", "touchend"].forEach(function(eventType){
    [].forEach.call(document.getElementsByClassName("getcolor-tabssection__tab"), function(tabButton){
        tabButton.addEventListener(eventType, function(){
            switchTabContent(tabButton.id);
        });
    });
});
/* Get tab tag from button ID */
function getTabTagFromButtonID(buttonID) {
    return buttonID.split("__")[1].split("_")[1];
}
/* Swith tab content */
function switchTabContent(currentTabID) {
    tabSections = document.getElementsByClassName("getcolor-tabsection");
    tabButtons = document.getElementsByClassName("getcolor-tabssection__tab");
    let currentState = document.getElementById("getcolor-interface__window").getAttribute("data-info");
    for (tabSection of tabSections) {
        if (tabSection.classList.contains("unvisible")) {
            if (tabSection.getAttribute("data-info") == getTabTagFromButtonID(currentTabID)) {
                tabSection.classList.toggle("unvisible");
                if ((tabSection.classList.contains("getcolor-codeblock")) && (tabSection.getAttribute("data-info") == "gradient")) {
                    if ((buttonGradientRadial.classList.contains("unvisible")) 
                    && (buttonInformation.getProperty(currentState, "gradienttype") == "radial-gradient")) {
                        buttonGradientLinear.click();
                    } else if ((buttonGradientLinear.classList.contains("unvisible")) 
                    && (buttonInformation.getProperty(currentState, "gradienttype") == "linear-gradient")) {
                        buttonGradientRadial.click();
                    }
                    displayLineNumbers("getcolor");
                    highlightCssCode("getcolor");
                } else if ((tabSection.classList.contains("getcolor-fillswitcher")) && (tabSection.getAttribute("data-info") == "color")) {
                    setTimeout(() => {
                        changePickerCursor();
                        changeLinePickerCursor();
                    }, 50);
                    if ((currentState != "normal") && (currentState != "hover") && (currentState != "pressed"))
                        tabSection.classList.toggle("unvisible");
                }
            }
        } else {
            if (tabSection.getAttribute("data-info") != getTabTagFromButtonID(currentTabID)) {
                tabSection.classList.toggle("unvisible");
            }
        }
    }
    for (tabButton of tabButtons) {
        if (tabButton.classList.contains("getcolor-tabssection__tab_active")) {
            if (tabButton.id != currentTabID)
                tabButton.classList.toggle("getcolor-tabssection__tab_active");
        } else {
            if (tabButton.id == currentTabID)
                tabButton.classList.toggle("getcolor-tabssection__tab_active");
        }
    }
}