/*
 *  GREYD TinyMCE Colorpicker
 *  
 *  based on: /wp-includes/js/tinymce/plugins/textcolor/plugin.js
 */
(function () {
    var colorPicker = (function () {
        'use strict';
        
        var pluginname = 'colorPicker';
        var debug = false;
        
        // globals
        var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
        var global$0 = tinymce.util.Tools.resolve('tinymce.Formatter');
        var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
        var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools');
        var global$3 = tinymce.util.Tools.resolve('tinymce.util.I18n');
        
        const cols = 9;
        const rows = 2;
        
        // Settings
        const defaultColorMap = [
            '11',
            'Branding - Primär',
            '12',
            'Branding - Sekundär',
            '13',
            'Branding - Alternative',
            '31',
            'Dunkel - Sehr dunkel',
            '21',
            'Dunkel - Dunkel',
            '32',
            'Dunkel - Leicht dunkel',
            '22',
            'Hell - Leicht hell',
            '33',
            'Hell - Hell',
            '23',
            'Hell - Sehr hell',
            '41',
            'Signalfarben - Hinweis dunkel',
            '51',
            'Signalfarben - Hinweis hell',
            '42',
            'Signalfarben - Erfolg dunkel',
            '52',
            'Signalfarben - Erfolg hell',
            '43',
            'Signalfarben - Fehler dunkel',
            '53',
            'Signalfarben - Fehler hell',
            '61',
            'Grundfarben - Schwarz',
            '62',
            'Grundfarben - Weiß',
        ];
        var getForeColorMap = function (editor) {
            var colorMap = [...defaultColorMap];
            var i = 0;
            for (i; i < colorMap.length; i += 2) {
                colorMap[i] = 'has-color-'+colorMap[i];
            }
            return colorMap;
        };
        var getBackColorMap = function (editor) {
            var colorMap = [...defaultColorMap];
            if (debug) console.log(colorMap);
            var i = 0;
            for (i; i < colorMap.length; i += 2) {
                colorMap[i] = 'bg-color-'+colorMap[i];
            }
            return colorMap;
        };
        var getColorID = function (color) {
            return color.replace(/[^0-9]/g, '');
        }
        
        // Add plugin
        global.add(pluginname, function (editor) {
            
            // init format
            editor.once('init', function () {
                editor.formatter.register('bgcolor', {
                    inline: 'span',
                    classes: '%value',
                    remove: 'empty'
                });
                editor.formatter.register('txtcolor', {
                    inline: 'span',
                    classes: '%value',
                    remove: 'empty'
                });
            });
            
            // register toolbar
            editor.addButton('foreColorPicker', {
                type: 'colorbutton',
                icon: 'forecolor',
                tooltip: 'Text color',
                format: 'txtcolor',
                panel: {
                    role: 'application',
                    ariaRemember: true,
                    html: renderPanelHtml(editor, true),
                    onclick: onPanelClick(editor)
                },
                onclick: onButtonClick(editor)
            });
            editor.addButton('backColorPicker', {
                type: 'colorbutton',
                icon: 'backcolor',
                tooltip: 'Background color',
                format: 'bgcolor',
                panel: {
                    role: 'application',
                    ariaRemember: true,
                    html: renderPanelHtml(editor, false),
                    onclick: onPanelClick(editor)
                },
                onpostrender: onButtonRender(editor),
                onclick: onButtonClick(editor)
            });
            
            // register Commands
            editor.addCommand('mceApplyColorPicker', function (format, value) {
                applyFormat(editor, format, value);
            });
            editor.addCommand('mceRemoveColorPicker', function (format) {
                removeFormat(editor, format);
            });
        });
        
        /*
            Toolbar
        */
        var onButtonRender = function (editor) {
            if (debug) console.log(editor)
        }
        
        // toggle panel
        var onButtonClick = function (editor) {
            return function (e) {
                if (debug) console.log('onButtonClick');
                var ctrl = e.control;
                if (ctrl._color) {
                    editor.execCommand('mceApplyColorPicker', ctrl.settings.format, ctrl._color);
                } else {
                    editor.execCommand('mceRemoveColorPicker', ctrl.settings.format);
                }
            };
        };
        
        // get panel html
        var renderPanelHtml = function (editor, foreColor) {
            return function () {
                var colorMap = foreColor ? getForeColorMap(editor) : getBackColorMap(editor);
                return getPanelHtml(cols, rows, colorMap);
            };
        };
        
        // panel html
        var getPanelHtml = function (cols, rows, colorMap) {
            if (debug) console.log('getPanelHtml');
            var colors, color, html, last, x, y, i, count = 0;
            var id = global$1.DOM.uniqueId('mcearia');

            var getColorCellHtml = function (color, title) {
                var isNoColor = color === 'transparent';
                return '<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' + '<div id="' + id + '-' + count++ + '"' + ' data-mce-color="' + (color ? color : '') + '"' + ' role="option"' + ' tabIndex="-1"' + ' class="' + (color ? 'bg-color-' + getColorID(color) : '') + '"' + ' title="' + global$3.translate(title) + '">' + (isNoColor ? '&#215;' : '') + '</div>' + '</td>';
            };
            colors = mapColors(colorMap);
            colors.push({
                text: global$3.translate('No color'),
                color: 'transparent'
            });
            html = '<table class="mce-grid mce-grid-border mce-colorbutton-grid greyd-color-picker" role="list" cellspacing="0"><tbody>';
            last = colors.length - 1;
            for (y = 0; y < rows; y++) {
                html += '<tr>';
                for (x = 0; x < cols; x++) {
                    i = y * cols + x;
                    if (i > last) {
                        html += '<td></td>';
                    } else {
                        color = colors[i];
                        html += getColorCellHtml(color.color, color.text);
                    }
                }
                html += '</tr>';
            }
            
            // custom color
            var getCustomColorCellHtml = function (color, title) {
                var isNoColor = color === 'transparent';
                return '<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' + '<div id="' + id + '-' + count++ + '"' + ' data-mce-color="' + (color ? color : '') + '"' + ' role="option"' + ' tabIndex="-1"' + ' style="' + (color ? 'background-color: ' + color : '') + '"' + ' title="' + global$3.translate(title) + '">' + (isNoColor ? '&#215;' : '') + '</div>' + '</td>';
            };
            html += '<tr>' + '<td colspan="' + cols + '" class="mce-custom-color-btn">' + '<div id="' + id + '-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" ' + 'role="button" tabindex="-1" aria-labelledby="' + id + '-c" style="width: 100%">' + '<button type="button" role="presentation" tabindex="-1">' + global$3.translate('Custom...') + '</button>' + '</div>' + '</td>' + '</tr>';
            html += '<tr>';
            for (x = 0; x < cols; x++) {
              html += getCustomColorCellHtml('', 'Custom color');
            }
            html += '</tr>';
            
            html += '</tbody></table>';
            return html;
        };
        
        // return formatted array
        var mapColors = function (colorMap) {
            if (debug) console.log('mapColors');
            var i;
            var colors = [];
            for (i = 0; i < colorMap.length; i += 2) {
                colors.push({
                    text: colorMap[i + 1],
                    color: colorMap[i]
                });
            }
            return colors;
        };
        
        /*
            Execute
        */
        
        // on color click
        var onPanelClick = function (editor) {
            return function (e) {
                if (debug) console.log('onPanelClick');
                
                // some vars
                var buttonCtrl = this.parent();
                var value;
                var custom = false;
                if (debug) console.log( buttonCtrl.$el[0] );
                
                // apply function for later access
                var selectColor = function (value, custom=false) {
                    var format = buttonCtrl.settings.format;
                    var _format = format === 'txtcolor' ? 'forecolor' : 'hilitecolor';
                    
                    if (custom) format = _format; // if this is a custom color, apply the custom format instead
                    else editor.execCommand('mceRemoveColorPicker', _format); // else remove the custom format
                    
                    editor.execCommand('mceApplyColorPicker', format, value);
                    buttonCtrl.hidePanel();
                    if (custom) {
                        buttonCtrl.color(value);
                    } else { 
                        buttonCtrl.resetColor();
                        $( buttonCtrl.$el[0] ).find('.mce-preview').removeClass().addClass( 'mce-preview bg-color-'+getColorID(value) );
                    }
                };
                
                // reset function for later access
                var resetColor = function () {
                    // reset both formats
                    var formats = [
                        buttonCtrl.settings.format,
                        buttonCtrl.settings.format === 'txtcolor' ? 'forecolor' : 'hilitecolor'
                    ];
                    formats.forEach( function(format) {
                        editor.execCommand('mceRemoveColorPicker', format);
                    } );
                    buttonCtrl.hidePanel();
                    $( buttonCtrl.$el[0] ).find('.mce-preview').removeClass().addClass('mce-preview');
                    buttonCtrl.resetColor();
                };
                
                // if custom colorpicker
                if (global$1.DOM.getParent(e.target, '.mce-custom-color-btn')) {
                    custom = true;
                    buttonCtrl.hidePanel();
                    var colorPickerCallback = getColorPickerCallback(editor);
                    colorPickerCallback.call(editor, function (value) {
                        var tableElm = buttonCtrl.panel.getEl().getElementsByTagName('table')[0];
                        var customColorCells, div, i;
                        customColorCells = global$2.map(tableElm.rows[tableElm.rows.length - 1].childNodes, function (elm) {
                            return elm.firstChild;
                        });
                        for (i = 0; i < customColorCells.length; i++) {
                            div = customColorCells[i];
                            if (!div.getAttribute('data-mce-color')) {
                                break;
                            }
                        }
                        if (i === cols) {
                            for (i = 0; i < cols - 1; i++) {
                                setDivColor(customColorCells[i], customColorCells[i + 1].getAttribute('data-mce-color'));
                            }
                        }
                        setDivColor(div, value);
                        selectColor(value, custom);
                    }, '');
                }
                
                value = e.target.getAttribute('data-mce-color');
                if (value) {
                    removeCurrentColor(editor, buttonCtrl.settings.format);
                    if (this.lastId) {
                        global$1.DOM.get(this.lastId).setAttribute('aria-selected', 'false');
                    }
                    e.target.setAttribute('aria-selected', true);
                    this.lastId = e.target.id;
                    if (value === 'transparent') {
                        resetColor();
                    } else {
                        // check if this is a previously created custom-color
                        custom = value.indexOf('#') !== -1 ? true : custom;
                        selectColor(value, custom);
                    }
                } else if (value !== null) {
                    buttonCtrl.hidePanel();
                }
            };
        };
        
        // get custom color picker function
        var getColorPickerCallback = function (editor) {
            return editor.getParam('color_picker_callback', null);
        };
        var setDivColor = function setDivColor(div, value) {
            div.style.background = value;
            div.setAttribute('data-mce-color', value);
        };
        
        // get & remove current color-class
        var removeCurrentColor = function (editor, format) {
            if (debug) console.log('removeCurrentColor');
            var elm = editor.selection.getStart();
            var colors = format === 'txtcolor' ? elm.className.matchAll(/has-color-\d{0,2}/g) : elm.className.matchAll(/bg-color-\d{0,2}/g);
            if (colors !== null) {
                for (const color of colors) {
                    editor.dom.removeClass(elm, color[0]);
                }
            }
        };
        
        // apply format
        var applyFormat = function (editor, format, value) {
            if (debug) console.log('applyFormat(format: '+format+', value: '+value+')');
            editor.undoManager.transact(function () {
                editor.focus();
                editor.formatter.apply(format, {
                    value: value
                });
                editor.nodeChanged();
            });
        };
        
        // remove format (value === transparent)
        var removeFormat = function (editor, format) {
            if (debug) console.log('removeFormat(format: '+format+')');
            editor.undoManager.transact(function () {
                editor.focus();
                editor.formatter.remove(format, {
                    value: null
                }, null, true);
                editor.nodeChanged();
            });
        };

        function Plugin() {}

        return Plugin;

    }());
})();