/**!
 * wp-color-picker-alpha
 *
 * Overwrite Automattic Iris for enabled Alpha Channel in wpColorPicker
 * Only run in input and is defined data alpha in true
 *
 * Version: 3.0.0
 * https://github.com/kallookoo/wp-color-picker-alpha
 * Licensed under the GPLv2 license or later.
 */

(function ($, undef) {

    var myRbg
    var myHex
    var rgbFormat
    var color
    var wpColorPickerAlpha = {
        'version': 300
    };


    // Always try to use the last version of this script.
    if ('wpColorPickerAlpha' in window && 'version' in window.wpColorPickerAlpha) {
        var version = parseInt(window.wpColorPickerAlpha.version, 10);
        if (!isNaN(version) && version >= wpColorPickerAlpha.version) {
            return;
        }
    }

    // Prevent multiple initiations
    if (Color.fn.hasOwnProperty('to_s')) {
        return;
    }

    // Create new method to replace the `Color.toString()` inside the scripts.
    Color.fn.to_s = function (type) {
        type = (type || 'hex');
        // Change hex to rgba to return the correct color.
        if ('hex' === type && this._alpha < 1) {
            type = 'rgba';
        }

        var color = '';
        if ('hex' === type) {
            color = this.toString();
        } else if (!this.error) {
            color = this.toCSS(type).replace(/\(\s+/, '(').replace(/\s+\)/, ')');
        }
        return color;
    }

    // Register the global variable.
    window.wpColorPickerAlpha = wpColorPickerAlpha;

    // Background image encoded
    var backgroundImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAAHnlligAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNpi+P///4EDBxiAGMgCCCAGFB5AADGCRBgYDh48CCRZIJS9vT2QBAggFBkmBiSAogxFBiCAoHogAKIKAlBUYTELAiAmEtABEECk20G6BOmuIl0CIMBQ/IEMkO0myiSSraaaBhZcbkUOs0HuBwDplz5uFJ3Z4gAAAABJRU5ErkJggg==';

    /**
     * Iris
     */
    $.widget('a8c.iris', $.a8c.iris, {
        /**
         * Alpha options
         *
         * @since 3.0.0
         *
         * @type {Object}
         */
        alphaOptions: {
            alphaEnabled: false,
        },
        /**
         * Get the current color or the new color.
         *
         * @since 3.0.0
         * @access private
         *
         * @param {Object|*} The color instance if not defined return the cuurent color.
         *
         * @return {string} The element's color.
         */
        _getColor: function (color) {
            if (color === undef) {
                color = this._color;
            }

            if (this.alphaOptions.alphaEnabled) {
                color = color.to_s(this.alphaOptions.alphaColorType);
                if (!this.alphaOptions.alphaColorWithSpace) {
                    color = color.replace(/\s+/g, '');
                }
                return color;
            }
            return color.toString();
        },
        /**
         * Create widget
         *
         * @since 3.0.0
         * @access private
         *
         * @return {void}
         */
        _create: function () {
            try {
                // Try to get the wpColorPicker alpha options.
                this.alphaOptions = this.element.wpColorPicker('instance').alphaOptions;
            } catch (e) {
            }

            // We make sure there are all options
            $.extend({}, this.alphaOptions, {
                alphaEnabled: false,
                alphaCustomWidth: 130,
                alphaReset: false,
                alphaColorType: 'hex',
                alphaColorWithSpace: false,
            });

            this._super();
        },

        /**
         * Binds event listeners to the Iris.
         *
         * @since 3.0.0
         * @access private
         *
         * @return {void}
         */

        _addInputListeners: function (input) {
            var self = this,
                debounceTimeout = 100,
                callback = function (event) {
                    var val = input.val(),
                        color = new Color(val),
                        val = val.replace(/^(#|(rgb|hsl)a?)/, ''),
                        type = self.alphaOptions.alphaColorType;

                    input.removeClass('iris-error');

                    if (!color.error) {
                        // let's not do this on keyup for hex shortcodes
                        if ('hex' !== type || !(event.type === 'keyup' && val.match(/^[0-9a-fA-F]{3}$/))) {
                            // Compare color ( #AARRGGBB )
                            if (color.toIEOctoHex() !== self._color.toIEOctoHex()) {
                                self._setOption('color', self._getColor(color));
                            }
                        }
                    } else if (val !== '') {
                        input.addClass('iris-error');
                    }
                };

            input.on('change', callback).on('keyup', self._debounce(callback, debounceTimeout));

            // If we initialized hidden, show on first focus. The rest is up to you.
            if (self.options.hide) {
                input.one('focus', function () {
                    self.show();
                });
            }
        },

        /**
         * Init Controls
         *
         * @since 3.0.0
         * @access private
         *
         * @return {void}
         */
        _initControls: function () {
            this._super();

            if (this.alphaOptions.alphaEnabled) {
                // Create Alpha controls
                var self = this,
                    stripAlpha = self.controls.strip.clone(false, false),
                    stripAlphaSlider = stripAlpha.find('.iris-slider-offset'),
                    controls = {
                        stripAlpha: stripAlpha,
                        stripAlphaSlider: stripAlphaSlider
                    };

                stripAlpha.addClass('iris-strip-alpha');
                stripAlphaSlider.addClass('iris-slider-offset-alpha');
                stripAlpha.appendTo(self.picker.find('.iris-picker-inner'));

                // Push new controls
                $.each(controls, function (k, v) {
                    self.controls[k] = v;
                });

                // Create slider
                self.controls.stripAlphaSlider.slider({
                    orientation: 'vertical',
                    min: 0,
                    max: 100,
                    step: 1,
                    value: parseInt(self._color._alpha * 100),
                    slide: function (event, ui) {
                        self.active = 'strip';
                        // Update alpha value
                        self._color._alpha = parseFloat(ui.value / 100);
                        self._change.apply(self, arguments);
                    }
                });
            }
        },
        /**
         * Create the controls sizes
         *
         * @since 3.0.0
         * @access private
         *
         * @param {bool} reset Set to True for recreate the controls sizes.
         *
         * @return {void}
         */
        _dimensions: function (reset) {
            this._super(reset);

            if (this.alphaOptions.alphaEnabled) {
                var self = this,
                    opts = self.options,
                    controls = self.controls,
                    square = controls.square,
                    strip = self.picker.find('.iris-strip'),
                    innerWidth, squareWidth, stripWidth, stripMargin, totalWidth;

                /**
                 * I use Math.round() to avoid possible size errors,
                 * this function returns the value of a number rounded
                 * to the nearest integer.
                 *
                 * The width to append all widgets,
                 * if border is enabled, 22 is subtracted.
                 * 20 for css left and right property
                 * 2 for css border
                 */
                innerWidth = Math.round(self.picker.outerWidth(true) - (opts.border ? 22 : 0));
                // The width of the draggable, aka square.
                squareWidth = Math.round(square.outerWidth());
                // The width for the sliders
                stripWidth = Math.round((innerWidth - squareWidth) / 2);
                // The margin for the sliders
                stripMargin = Math.round(stripWidth / 2);
                // The total width of the elements.
                totalWidth = Math.round(squareWidth + (stripWidth * 2) + (stripMargin * 2));

                // Check and change if necessary.
                while (totalWidth > innerWidth) {
                    stripWidth = Math.round(stripWidth - 2);
                    stripMargin = Math.round(stripMargin - 1);
                    totalWidth = Math.round(squareWidth + (stripWidth * 2) + (stripMargin * 2));
                }


                square.css('margin', '0');
                strip.width(stripWidth).css('margin-left', stripMargin + 'px');
            }
        },
        /**
         * Callback to update the controls and the current color.
         *
         * @since 3.0.0
         * @access private
         *
         * @return {void}
         */
        _change: function () {
            var self = this,
                active = self.active;

            self._super();

            if (self.alphaOptions.alphaEnabled) {
                var controls = self.controls,
                    alpha = parseInt(self._color._alpha * 100),
                    color = self._color.toRgb(),
                    gradient = [
                        'rgb(' + color.r + ',' + color.g + ',' + color.b + ') 0%',
                        'rgba(' + color.r + ',' + color.g + ',' + color.b + ', 0) 100%'
                    ],
                    target = self.picker.closest('.wp-picker-container').find('.wp-color-result');

                self.options.color = self._getColor();
                // Generate background slider alpha, only for CSS3.
                controls.stripAlpha.css({'background': 'linear-gradient(to bottom, ' + gradient.join(', ') + '), url(' + backgroundImage + ')'});
                // Update alpha value
                if (active) {
                    controls.stripAlphaSlider.slider('value', alpha);
                }

                if (!self._color.error) {
                    self.element.removeClass('iris-error').val(self.options.color);
                }

                self.picker.find('.iris-palette-container').on('click.palette', '.iris-palette', function () {
                    var color = $(this).data('color');
                    if (self.alphaOptions.alphaReset) {
                        self._color._alpha = 1;
                        color = self._getColor();
                    }
                    self._setOption('color', color);
                });
            }
        },
        /**
         * Paint dimensions.
         *
         * @since 3.0.0
         * @access private
         *
         * @param {string} origin  Origin (position).
         * @param {string} control Type of the control,
         *
         * @return {void}
         */
        _paintDimension: function (origin, control) {
            var self = this,
                color = false;

            // Fix for slider hue opacity.
            if (self.alphaOptions.alphaEnabled && 'strip' === control) {
                color = self._color;
                self._color = new Color(color.toString());
                self.hue = self._color.h();
            }

            self._super(origin, control);

            // Restore the color after paint.
            if (color) {
                self._color = color;
            }
        },
        /**
         * To update the options, see original source to view the available options.
         *
         * @since 3.0.0
         *
         * @param {string} key   The Option name.
         * @param {mixed} value  The Option value to update.
         *
         * @return {void}
         */
        _setOption: function (key, value) {
            var self = this;
            if ('color' === key && self.alphaOptions.alphaEnabled) {
                // cast to string in case we have a number
                value = '' + value;
                newColor = new Color(value).setHSpace(self.options.mode);
                // Check if error && Check the color to prevent callbacks with the same color.
                if (!newColor.error && self._getColor(newColor) !== self._getColor()) {
                    self._color = newColor;
                    self.options.color = self._getColor();
                    self.active = 'external';
                    self._change();
                }
            } else {
                return self._super(key, value);
            }
        },
        /**
         * Returns the iris object if no new color is provided. If a new color is provided, it sets the new color.
         *
         * @param newColor {string|*} The new color to use. Can be undefined.
         *
         * @since 3.0.0
         *
         * @return {string} The element's color.
         */
        color: function (newColor) {
            if (newColor === true) {
                return this._color.clone();
            }
            if (newColor === undef) {
                return this._getColor();
            }
            this.option('color', newColor);
        },
    });

    /**
     * wpColorPicker
     */
    $.widget('wp.wpColorPicker', $.wp.wpColorPicker, {
        /**
         * Alpha options
         *
         * @since 3.0.0
         *
         * @type {Object}
         */
        alphaOptions: {
            alphaEnabled: false,
        },
        /**
         * Get the alpha options.
         *
         * @since 3.0.0
         * @access private
         *
         * @return {object} The current alpha options.
         */
        _getAlphaOptions: function () {
            var el = this.element,
                type = (el.data('type') || this.options.type),
                color = (el.data('defaultColor') || el.val()),
                options = {
                    alphaEnabled: (el.data('alphaEnabled') || false),
                    alphaCustomWidth: 130,
                    alphaReset: false,
                    alphaColorType: 'rgb',
                    alphaColorWithSpace: false,
                };

            if (options.alphaEnabled) {
                options.alphaEnabled = (el.is('input') && 'full' === type);
            }

            if (!options.alphaEnabled) {
                return options;
            }

            options.alphaColorWithSpace = (color && color.match(/\s/));

            $.each(options, function (name, defaultValue) {
                var value = (el.data(name) || defaultValue);
                switch (name) {
                    case 'alphaCustomWidth':
                        value = (value ? parseInt(value, 10) : 0);
                        value = (isNaN(value) ? defaultValue : value);
                        break;
                    case 'alphaColorType':
                        if (!value.match(/^(hex|(rgb|hsl)a?)$/)) {
                            if (color && color.match(/^#/)) {
                                value = 'hex';
                            } else if (color && color.match(/^hsla?/)) {
                                value = 'hsl';
                            } else {
                                value = defaultValue;
                            }
                        }
                        break;
                    default:
                        value = !!value;
                        break;
                }
                options[name] = value;
            });

            return options;
        },
        /**
         * Create widget
         *
         * @since 3.0.0
         * @access private
         *
         * @return {void}
         */
        _create: function () {
            // Return early if Iris support is missing.
            if (!$.support.iris) {
                return;
            }

            // Set the alpha options for the current instance.
            this.alphaOptions = this._getAlphaOptions();

            // Create widget.
            this._super();
            this.loadUI();
        },
        /**
         * Binds event listeners to the color picker and create options, etc...
         *
         * @since 3.0.0
         * @access private
         *
         * @return {void}
         */
        _addListeners: function () {
            if (!this.alphaOptions.alphaEnabled) {
                return this._super();
            }

            var self = this,
                el = self.element,
                isDeprecated = self.toggler.is('a');

            this.alphaOptions.defaultWidth = el.width();
            if (this.alphaOptions.alphaCustomWidth) {
                el.width(parseInt(this.alphaOptions.defaultWidth + this.alphaOptions.alphaCustomWidth, 10));
            }

            self.toggler.css({
                'position': 'relative',
                'background-image': 'url(' + backgroundImage + ')'
            });

            if (isDeprecated) {
                self.toggler.html('<span class="color-alpha" />');
            } else {
                self.toggler.append('<span class="color-alpha" />');
            }

            self.colorAlpha = self.toggler.find('span.color-alpha').css({
                'width': '30px',
                'height': '100%',
                'position': 'absolute',
                'top': 0,
                'background-color': el.val(),
            });

            // Define the correct position for ltr or rtl direction.
            if ('ltr' === self.colorAlpha.css('direction')) {
                self.colorAlpha.css({
                    'border-bottom-left-radius': '2px',
                    'border-top-left-radius': '2px',
                    'left': 0
                });
            } else {
                self.colorAlpha.css({
                    'border-bottom-right-radius': '2px',
                    'border-top-right-radius': '2px',
                    'right': 0
                });
            }

            el.iris({
                /**
                 * @summary Handles the onChange event if one has been defined in the options.
                 *
                 * Handles the onChange event if one has been defined in the options and additionally
                 * sets the background color for the toggler element.
                 *
                 * @since 3.0.0
                 *
                 * @param {Event} event    The event that's being called.
                 * @param {HTMLElement} ui The HTMLElement containing the color picker.
                 *
                 * @returns {void}
                 */
                change: function (event, ui) {
                    self.colorAlpha.css({'background-color': ui.color.to_s(self.alphaOptions.alphaColorType)});

                    /* --- changes in js --- */
                    /* --- changes in js --- */
                    myRbg = ui.color.to_s(self.alphaOptions.alphaColorType)

                    selfAlphaSibs = self.colorAlpha[0].parentNode.nextSibling

                    selfAlphaSibs.lastElementChild.innerText = myRbg
                    rgbFormat = myRbg
                    var isAlpha = false;
                    var a = 1;
                    if (rgbFormat.includes('rgba(')) {
                        rgbFormat = rgbFormat.substring(rgbFormat.indexOf('rgba(') + 5, rgbFormat.indexOf(')'))
                        isAlpha = true;
                    } else {
                        rgbFormat = rgbFormat.substring(rgbFormat.indexOf('rgb(') + 4, rgbFormat.indexOf(')'))
                    }
                    color = rgbFormat.split(',')

                    r = parseInt(color[0])
                    g = parseInt(color[1])
                    b = parseInt(color[2])
                    if (color.includes("#")) myHex = color
                    else {
                        if (isAlpha) {
                            var alpha = toHex(color[3] * 256) || 0o0;
                            myHex = '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1) + alpha;
                        } else {
                            myHex = '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
                        }
                    }

                    selfAlphaSibs.firstElementChild.innerText = myHex


                    // fire change callback if we have one
                    if ($.isFunction(self.options.change)) {
                        self.options.change.call(this, event, ui);
                    }

                },
            });

            /**
             * Prevent any clicks inside this widget from leaking to the top and closing it.
             *
             * @since 3.0.0
             *
             * @param {Event} event The event that's being called.
             *
             * @return {void}
             */
            self.wrap.on('click.wpcolorpicker', function (event) {
                event.stopPropagation();
            });

            /**
             * Open or close the color picker depending on the class.
             *
             * @since 3.0.0
             */

            self.toggler.click(function () {
                if (self.toggler.hasClass('wp-picker-open')) {
                    self.close();
                } else {
                    self.open();
                }
            });

            /**
             * Checks if value is empty when changing the color in the color picker.
             * If so, the background color is cleared.
             *
             * @since 3.0.0
             *
             * @param {Event} event The event that's being called.
             *
             * @return {void}
             */
            el.change(function (event) {
                var val = $(this).val();

                if (el.hasClass('iris-error') || val === '' || val.match(/^(#|(rgb|hsl)a?)$/)) {
                    if (isDeprecated) {
                        self.toggler.removeAttr('style');
                    }

                    self.colorAlpha.css('background-color', '');

                    // fire clear callback if we have one
                    if ($.isFunction(self.options.clear)) {
                        self.options.clear.call(this, event);
                    }
                }
            });

            /**
             * Enables the user to either clear the color in the color picker or revert back to the default color.
             *
             * @since 3.0.0
             *
             * @param {Event} event The event that's being called.
             *
             * @return {void}
             */
            self.button.click(function (event) {
                if ($(this).hasClass('wp-picker-default')) {
                    el.val(self.options.defaultColor).change();
                } else if ($(this).hasClass('wp-picker-clear')) {
                    el.val('');
                    if (isDeprecated) {
                        self.toggler.removeAttr('style');
                    }

                    self.colorAlpha.css('background-color', '');

                    // fire clear callback if we have one
                    if ($.isFunction(self.options.clear)) {
                        self.options.clear.call(this, event);
                    }

                    el.trigger('change');
                }
            });
        },
        loadUI: function () {
            var currentPicker
            var wpInnerCont
            var rgbAndHexShower

            var defaultColor
            var defHex
            var defRgb
            var loadInterval

            var input = jQuery(this.element);
            if (!input.hasClass('digits_color_picker')) {
                return;
            }
            var wpPickerContainer = input.closest(".wp-picker-container")

            var clearInput = wpPickerContainer.find(".wp-picker-input-wrap")
            var colorResult = wpPickerContainer.find(".wp-color-result")

            defaultColor = input.val();

            var a = 1;

            if (defaultColor.includes("#")) {
                r = parseInt(defaultColor.slice(1, 3), 16)
                g = parseInt(defaultColor.slice(3, 5), 16)
                b = parseInt(defaultColor.slice(5, 7), 16)
                a = 1
            } else {
                if (defaultColor.includes('rgba(')) defaultColor = defaultColor.substring(defaultColor.indexOf('rgba(') + 5, defaultColor.indexOf(')'))
                else defaultColor = defaultColor.substring(defaultColor.indexOf('rgb(') + 4, defaultColor.indexOf(')'))

                color = defaultColor.split(',')
                r = parseInt(color[0])
                g = parseInt(color[1])
                b = parseInt(color[2])
                a = color[3] ? parseFloat(color[3]) : 1
            }

            if (a === 1) defRgb = `rgb(${r}, ${g}, ${b})`
            else defRgb = `rgba(${r},${g},${b},${a})`

            var alpha = toHex(a * 256) || 0o0;
            if (a === 1) {
                alpha = '';
            }
            defHex = '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1) + alpha;

            clearInput.hide();

            rgbAndHexShower =
                `<div class="show-texts">
                <span class="show-hexes color_picker_edit color_picker_hex_edit" contenteditable="true">${defHex}</span>
                <span class="text-style-or dig-color-picker_hide">or</span>
                <span class="show-RGBs color_picker_edit color_picker_rgba_edit dig-color-picker_hide" contenteditable="true">${defRgb}</span>
            </div>
            
            <div class="digits-select-color select-color">
                Select
            </div>
        `

            wpInnerCont = jQuery(rgbAndHexShower);
            colorResult.wrap("<div class='select-bar'></div>").after(wpInnerCont);

            var updateInterval;

            wpPickerContainer.find('.color_picker_edit').on('input', function (e) {
                var editor = jQuery(this);
                clearTimeout(updateInterval);
                updateInterval = setTimeout(function () {
                    var text = editor.text();
                    input.val(text).trigger('change');
                }, 450);
            })

            wpPickerContainer.find('.digits-select-color').on('click', function (e) {
                e.preventDefault();
                jQuery(this).closest('.wp-picker-container').find('.wp-color-result').trigger('click');
            })
        },
    });

    function toHex(val) {
        val = parseInt(val);
        val = Math.max(0, val);
        val = Math.min(val, 255);
        val = Math.ceil(val);
        return "0123456789ABCDEF".charAt((val - val % 16) / 16) + "0123456789ABCDEF".charAt(val % 16);
    }
}(jQuery));
