(function( $ ) {
    /**
	 * Return font's weight in css format
	 *
	 * @param string weight font's weight
     * @return string weight in css format (100-900)
	 */
	const sunsetConvertFontWeightToCss = ( weight = 'regular' ) => {

		if ( weight === 'regular' || weight === 'italic' ) {
			return '400';
		}

		let cssWeight = weight.replace(/[^0-9.]/g, '');

		return cssWeight;
	}

    /**
	 * Return font's style in css format
	 *
	 * @param string weight font's weight with or without style variant
     * @return string font style in css format
	 */
	const sunsetConvertFontStyleToCss = ( weight = 'regular' ) => {

		if ( weight === 'regular' ) {
			return 'normal';
		}

		if ( weight === 'italic' || weight.indexOf('italic') !== -1 ) {
			return 'italic';
		}

		return 'normal';
	}

    /**
     * Handles Media upload popup window
     * @param {string} buttonClass css selector for a button to attach Media upload popup window
     */
    function sunsetMediaUpload(buttonClass) {
        'use strict';
        jQuery('body').on('click', buttonClass, function () {
            let buttonId = '#' + jQuery(this).attr('id');
            let inputField = jQuery(this).siblings('input.sunset-media-id');
            let previewImg = jQuery(this).closest('.customize-control').find('img');
            let delButton = jQuery(this).closest('.customize-control').find('.sunset-delete-media-button');
    
            wp.media.editor.send.attachment = function (props, attachment) {    
                if (typeof inputField !== 'undefined') {
                    inputField.val(attachment.id);
                    inputField.trigger('change');
                    previewImg.attr("src", typeof attachment.sizes.thumbnail !== 'undefined' ? attachment.sizes.thumbnail.url : attachment.url);
                    previewImg.attr("srcset", "");
                    previewImg.show();
                    delButton.show();
                }
            };
            wp.media.editor.open(buttonClass);
            window.send_to_editor = function (html) {
                
            };
            return false;
        });
    }

    /**
     * Converts HTML special characters to their entity equivalents
     * @param {string} string 
     * @returns string
     */
    const sunsetEscapeHtml = (string) => {
        'use strict';
        //noinspection JSUnresolvedFunction
        string = String(string).replace(new RegExp('\r?\n', 'g'), '<br />');
        string = String(string).replace(/\\/g, '&#92;');
        return String(string).replace(/[&<>"'\/]/g, function (s) {
            return entityMap[s];
        });
    
    }

    /**
     * Updates customizer's Social Link values
     */
    const sunsetRefreshSocialValues = () => {
        'use strict';
        jQuery('.customizer-social-link-control-container').each(function () {
            let values = [];
            let th = jQuery(this);
            th.find('.customizer-social-link-control').each(function () {
    
                let text = jQuery(this).find('.customize-control-social-link-name').val();
                let link = jQuery(this).find('.customize-control-social-link-url').val();
                let icon = jQuery(this).find('.customize-control-social-link-icon-url').val();
                let icon_type = jQuery(this).find('.customize-control-social-link-icon-type').val();
                let icon_color = jQuery(this).find('.customize-control-social-link-icon-color').val();
                let icon_hover_color = jQuery(this).find('.customize-control-social-link-icon-hover-color').val();
    
                if (text !== '' || link !== '') {
                    values.push({
                        'text': sunsetEscapeHtml(text),
                        'link': link,                        
                        'icon': icon,                     
                        'icon_type': icon_type,                 
                        'icon_color': icon_color,                 
                        'icon_hover_color': icon_hover_color,                 
                    });
                }
               
            });
            th.find('.customizer-social-link-colector').val(JSON.stringify(values));
            th.find('.customizer-social-link-colector').trigger('change');
        });
    }

    /**
     * Move item in sortable list up
     * @param {HTMLCollection} $item jQuery element to move up
     */
    const sunsetMoveItemUp = ($item) => {
        $before = $item.prev();
        $item.insertBefore($before);
    }
    
    /**
     * Move item in sortable list down
     * @param {HTMLCollection} $item jQuery element to move down
     */
    const sunsetMoveItemDown = ($item) => {
        $after = $item.next();
        $item.insertAfter($after);
    }

    /**
     * Updates arrows in sortable list
     * @param {HTMLCollection} $reorderNav jQuery element where update arrows
     */
    const sunsetUpdateOrderArrows = ($reorderNav) => {
        $reorderNav.each(function(){
            let index = $(this).closest('.customizer-social-link-control').index();
            let max = $(this).closest('.ui-sortable').find('.customizer-social-link-control').length;
            if (index === 0) {
                $(this).find('.menus-move-up').attr("tabindex", '-1');
                $(this).find('.menus-move-up').attr("aria-hidden", true);
                $(this).closest('.customizer-social-link-control').removeClass('move-down-disabled');
                $(this).closest('.customizer-social-link-control').addClass('move-up-disabled');
            }
            if (index === (max - 1)) {
                $(this).find('.menus-move-down').attr("tabindex", '-1');
                $(this).find('.menus-move-down').attr("aria-hidden", true);
                $(this).closest('.customizer-social-link-control').removeClass('move-up-disabled');
                $(this).closest('.customizer-social-link-control').addClass('move-down-disabled');
            }
            if (index !== 0 && index !== (max - 1)) {
                $(this).find('.menus-move-up').attr("tabindex", '0');
                $(this).find('.menus-move-up').attr("aria-hidden", false);
                $(this).find('.menus-move-down').attr("tabindex", '0');
                $(this).find('.menus-move-down').attr("aria-hidden", false);
                $(this).closest('.customizer-social-link-control').removeClass('move-down-disabled');
                $(this).closest('.customizer-social-link-control').removeClass('move-up-disabled');
            }
        })
    }

    wp.customize.bind( 'ready', function() {
        console.log('Customizer controls are ready')

        /**
         * Copies classes from original <select><option> to select2 options
         * https://select2.org/dropdown
         * @param {*} data 
         * @param {*} container 
         * @returns string
         */
        const select2CopyClasses = (data, container) => {
            if (data.element) {
                $(container).addClass($(data.element).attr("class"));
            }
            return data.text;
        }

        // append select2 to all select inputs
        $('.customize-control select[multiple]').each(function(){
            $(this).select2({
                dropdownParent: $('#customize-controls'),
                templateResult: select2CopyClasses,
            });
        });
        $('.customize-control select:not([multiple])').each(function(){
            $(this).select2({
                dropdownParent: $('#customize-controls'),
                allowClear: false,                
                templateResult: select2CopyClasses,
            });
        })

        /**
         * Get weights for a Google Font via AJAX
         * @param {string} newVal value of a font
         * @param {HTMLCollection} container jQuery element with font options
         * @param {HTMLCollection} select jQuery dropdown with font weights
         * @param {object} event 
         */
        const getFontWeights = (newVal, container, select, event) => {
            // Send our request to the sunset_get_google_font_ajax function
            jQuery.ajax({
                type: 'POST',
                url: sunset_ajax.url,
                data: {
                    action: 'sunset_get_google_font_ajax',
                    sunset_nonce : sunset_ajax.nonce,
                    font: newVal
                },
                async: true,
                dataType: 'json',
                beforeSend: function( ) {
                    container.block({ message: null, overlayCSS: { backgroundColor: '#fff' } });
                },
                success: function( response ) {
                    let font_weights = response;

                    container.unblock();

                    if (Object.keys(font_weights).length > 0) {
                        select.find('option').remove();
                        for (let i in font_weights) {
                            let selected = (i === 'regular' ? 'selected' : '');
                            select.append($(`<option class="font-weight-${i}" ${selected} />`).val(i).text(font_weights[i]));
                        }
                        select.change();

                        // https://iandunn.name/2019/11/21/sending-custom-data-between-wordpress-customizer-preview-and-controls-panes/ 

                        const iframe = document.getElementById( 'customize-preview' ).getElementsByTagName( 'iframe' )[0];

                        const messenger = new wp.customize.Messenger( {
                            channel      : 'sunset-theme',
                            targetWindow : iframe.contentWindow,
                            url          : wp.customize.settings.url.allowed[ 0 ],
                        } );

                        const message = { 
                            weight : sunsetConvertFontWeightToCss(select.val()),
                            style : sunsetConvertFontStyleToCss(select.val()),
                        };

                        messenger.send( event, message );
                        
                    }
                },
                error: function(errObj, errStatus) {
                    container.unblock();
                    console.log(errObj, errStatus);
                }
            });
        }

        /**
         * Updates font value after change
         * @param {object} e event
         */
        const updateFont = (e) => {
            let fontControl = $(e.target).closest('.customize-control-font');
            const fontControlHidden = fontControl.find('.customize-control-google-font-selection');

            let selectedFont = {
                font: fontControl.find('.customize-control-font-family').val(),
                weight: fontControl.find('.customize-control-font-weight').val(),
                transform: fontControl.find('.customize-control-font-transform').val(),
                size: fontControl.find('.customize-control-font-size').val(),
                stroke: fontControl.find('.customize-control-font-stroke').prop("checked"),
            };
    
            // Important! Make sure to trigger change event so Customizer knows it has to save the field
            fontControlHidden.val(JSON.stringify(selectedFont)).trigger('change');
        }

        /**
         * Clears values in Social Link Control element
         * @param {HTMLCollection} controlEl - a jQuery control element to clear values
         */
        const clearSocialControl = (controlEl) => {
            controlEl.find('.customize-control-social-link-name').val('');
            controlEl.find('.customize-control-social-link-url').val('');
            controlEl.find('.customize-control-social-link-icon-url').val('');
            controlEl.find('.customize-control-social-link-icon-type').val('');
            controlEl.find('.customize-control-social-link-icon-color').val('');
            controlEl.find('.customize-control-social-link-icon-hover-color').val('');
            controlEl.find('.customize-control-social-link-icon-preview').hide();
            controlEl.find('.menu-item-title').text('');
            controlEl.find('.customize-control-icons-set input:radio').prop('checked', false);

            // Expand the item
            controlEl.toggleClass('menu-item-edit-inactive');
            controlEl.toggleClass('menu-item-edit-active');
            controlEl.find('.menu-item-settings').slideToggle();

            /** Remove color pickers and reinit them */
            controlEl.find('.wp-picker-container').remove();
            controlEl.find('.field-color--color').append('<input class="customize-control-social-link-input customize-control-social-link-icon-color" type="text" />')
            controlEl.find('.field-color--hover-color').append('<input class="customize-control-social-link-input customize-control-social-link-icon-hover-color" type="text" />')

            applyColorPicker(controlEl.find('.customize-control-social-link-icon-color'));
            applyColorPicker(controlEl.find('.customize-control-social-link-icon-hover-color'));

            /*Refresh values*/
            controlEl.find('.customize-control-social-link-name').focus();
        }

        /**
         * Apply colorPicker for icons
         * 
         * @param {HTMLCollection} items jQuery elements to be applied for wpColorPicker
         */
        const applyColorPicker = (items) => {
            items.wpColorPicker({
                defaultColor: false,
                change: function(event, ui){
                    let element = event.target;
                    let color = ui.color.toString();

                    $(element).val(color);
                    sunsetRefreshSocialValues();
                },
                clear: function(event){ 
                    let element = jQuery(event.target).closest('.wp-picker-container').find('.wp-color-picker');
                    let color = '';

                    if (element.length > 0) {
                        element.val(color);
                        sunsetRefreshSocialValues();
                    }
                },
            });
        }

        
        // Trigger font update on weight change
        $('select.customize-control-font-weight').on('change', function(e){
            updateFont(e);
        })

        // Trigger font update on size change
        $('input.customize-control-font-size').on('change', function(e){
            updateFont(e);
        })

        // Trigger font update on stroke change
        $('input.customize-control-font-stroke').on('change', function(e){
            updateFont(e);
        })

        // Trigger font update on font family change and get new values for font weights
        $('select.customize-control-font-family').on('change', function(e){
            
            let fontContainer = $(e.target).closest('.customize-control-font');
            let fontWeightSelect = fontContainer.find('select.customize-control-font-weight');
            let fontFamily = $(this).val();

            updateFont(e);

            getFontWeights(fontFamily, fontContainer, fontWeightSelect, 'sunset_customizer_primary_font_weight_updated');
        })

        // Trigger font update on text transform change
        $('select.customize-control-font-transform').on('change', function(e){
            updateFont(e);
        })

        /*
         * Toggle visibility of Customizer's controls with 'postMessage' transport argument
        */
        wp.customize( 'sunset_header_fixed', function( value ) {
            value.bind( function( newVal ) {
                if ( !newVal ) {
                    wp.customize.control('sunset_header_fixed_type').deactivate();
                } else {
                    wp.customize.control('sunset_header_fixed_type').activate();
                }
                
            } );
        });

        wp.customize( 'sunset_header_add_border', function( value ) {
            value.bind( function( newVal ) {
                if ( !newVal ) {
                    wp.customize.control('sunset_header_border_color').deactivate();
                    wp.customize.control('sunset_header_border_height').deactivate();
                } else {
                    wp.customize.control('sunset_header_border_color').activate();
                    wp.customize.control('sunset_header_border_height').activate();
                }
                
            } );
        });

        wp.customize( 'sunset_topbar_add_border', function( value ) {
            value.bind( function( newVal ) {
                if ( !newVal ) {
                    wp.customize.control('sunset_topbar_border_color').deactivate();
                    wp.customize.control('sunset_topbar_border_height').deactivate();
                } else {
                    wp.customize.control('sunset_topbar_border_color').activate();
                    wp.customize.control('sunset_topbar_border_height').activate();
                }
                
            } );
        });

        wp.customize( 'sunset_copyright_add_border', function( value ) {
            value.bind( function( newVal ) {
                if ( !newVal ) {
                    wp.customize.control('sunset_copyright_border_color').deactivate();
                    wp.customize.control('sunset_copyright_border_height').deactivate();
                } else {
                    wp.customize.control('sunset_copyright_border_color').activate();
                    wp.customize.control('sunset_copyright_border_height').activate();
                }
                
            } );
        });

        wp.customize( 'sunset_footer_add_border', function( value ) {
            value.bind( function( newVal ) {
                if ( !newVal ) {
                    wp.customize.control('sunset_footer_border_color').deactivate();
                    wp.customize.control('sunset_footer_border_height').deactivate();
                } else {
                    wp.customize.control('sunset_footer_border_color').activate();
                    wp.customize.control('sunset_footer_border_height').activate();
                }
                
            } );
        });

        // detect when customizer view has been changed
        wp.customize.previewedDevice.bind(function(new_device) {
            console.log('Reponsive view has been changed to: ' + new_device);
        });

        // switch preview mode to mobile when "sunset_header_mobile_options" section expanded
        wp.customize.section.each( function ( section ) { 

            section.expanded.bind( function( isExpanding ) {

                let sectionID = section.id;
    
                if ( sectionID === 'sunset_header_mobile_options' && isExpanding ) {
                    wp.customize.previewedDevice.set('mobile');
                }

                if ( sectionID === 'sunset_topbar_mobile_options' && isExpanding ) {
                    wp.customize.previewedDevice.set('mobile');
                }

                if ( sectionID === 'sunset_footer_mobile_options' && isExpanding ) {
                    wp.customize.previewedDevice.set('mobile');
                }                

                if ( sectionID === 'sunset_copyright_mobile_options' && isExpanding ) {
                    wp.customize.previewedDevice.set('mobile');
                }
    
            });    
    
        });

        let customizerThemeConrols = jQuery('#customize-theme-controls');
        let $reorderNav = customizerThemeConrols.find('.customizer-social-link-control').find( '.menu-item-reorder-nav' );

        /**
         * Handles click on Add new social item
         */
        customizerThemeConrols.on('click', '.customizer-add-new-social-link', function () {
            let th = jQuery(this).closest('.customize-control-social-link');
            if (typeof th !== 'undefined') {
                /* Clone the first box*/
                let field = th.find('.customizer-social-link-control:first').clone( true, true );

                if (typeof field !== 'undefined') {
                    /*Remove all repeater fields except first one*/

                    field.find('.customize-control-social-link-name').val('');
                    field.find('.customize-control-social-link-url').val('');
                    field.find('.customize-control-social-link-icon-url').val('');
                    field.find('.customize-control-social-link-icon-type').val('');
                    field.find('.customize-control-social-link-icon-color').val('');
                    field.find('.customize-control-social-link-icon-hover-color').val('');
                    field.find('.customize-control-social-link-icon-preview').hide();
                    field.find('.menu-item-title').text('');
                    field.find('.customize-control-icons-set input:radio').prop('checked', false);

                    // Expand the item
                    field.toggleClass('menu-item-edit-inactive');
                    field.toggleClass('menu-item-edit-active');
                    field.find('.menu-item-settings').slideToggle();

                    /*Append new box*/
                    th.find( ".customizer-social-link-control-container > ul.ui-sortable").append(field);

                    /** Remove color pickers and reinit them */
                    field.find('.wp-picker-container').remove();
                    field.find('.field-color--color').append('<input class="customize-control-social-link-input customize-control-social-link-icon-color" type="text" />')
                    field.find('.field-color--hover-color').append('<input class="customize-control-social-link-input customize-control-social-link-icon-hover-color" type="text" />')

                    applyColorPicker(field.find('.customize-control-social-link-icon-color'));
                    applyColorPicker(field.find('.customize-control-social-link-icon-hover-color'));

                    /*Refresh values*/
                    sunsetRefreshSocialValues();
                    sunsetUpdateOrderArrows($reorderNav);
                    field.find('.customize-control-social-link-name').focus();
                }

            }
            return false;
        });

        /**
         * Toggle reorder functionality
         */
        customizerThemeConrols.on('click', '.reorder-toggle', function () {
            jQuery(this).closest('.customizer-social-link-control-container').toggleClass('reordering');
        });

        /**
         * Toggle item settings
         */
        customizerThemeConrols.on('click', '.customizer-social-link-control .menu-item-bar', function () {
            jQuery(this).siblings('.menu-item-settings').slideToggle();
            jQuery(this).closest('.customizer-social-link-control').toggleClass('menu-item-edit-inactive');
            jQuery(this).closest('.customizer-social-link-control').toggleClass('menu-item-edit-active');
        })

        /**
         * Handle remove item 
         */
        customizerThemeConrols.on('click', '.customizer-remove-social-link', function () {
            let parent = jQuery(this).closest('.customizer-social-link-control');
            let controlsCount = jQuery(this).closest('.menu.ui-sortable').find('.customizer-social-link-control').length;
            if (typeof parent !== 'undefined' && controlsCount > 1) {
                parent.hide(500, function(){
                    parent.remove();
                    sunsetRefreshSocialValues();
                });
            }
            if (controlsCount === 1) {
                clearSocialControl(parent);
                jQuery(this).remove();
                sunsetRefreshSocialValues();
                sunsetUpdateOrderArrows($reorderNav);
            }
            return false;
        });

        /**
         * Handle change of the item's name or URL
         */
        customizerThemeConrols.on('change', '.customize-control-social-link-input',function(){
            sunsetRefreshSocialValues();

            if ($(this).hasClass('customize-control-social-link-name')) {
                jQuery(this).closest('.customizer-social-link-control').find('.menu-item-title').text(jQuery(this).val());
            }
            return false;
        });

        /**
         * Handle change of the item's icon
         */
        customizerThemeConrols.on('change', '.customize-control-icons-set input:radio',function(){
            let url = $(this).siblings('img').attr('src');
            let type = $(this).val();
            let titleEl = $(this).closest('.menu-item-settings').find('.customize-control-social-link-name');
            let socialNetworkName = $(this).val().split("-")[0];

            titleEl.val(socialNetworkName);
            $(this).closest(".customize-control-icons-set").find(".customize-control-social-link-icon-url").val(url);
            $(this).closest(".customize-control-icons-set").find(".customize-control-social-link-icon-type").val(type);
            sunsetRefreshSocialValues();
            return false;
        });

        /**
         * Handle clicks for up/down/left-right on the reorder nav. 
         */      
        $reorderNav.find( '.menus-move-up, .menus-move-down' ).on( 'click', function(e) {
            e.stopPropagation();
            var moveBtn = $( this );

            var isMoveUp = moveBtn.is( '.menus-move-up' ),
                isMoveDown = moveBtn.is( '.menus-move-down' );

            if ( isMoveUp ) {
                sunsetMoveItemUp(moveBtn.closest('.customizer-social-link-control'));
                moveBtn.focus();
            } else if ( isMoveDown ) {
                sunsetMoveItemDown(moveBtn.closest('.customizer-social-link-control'));
                moveBtn.focus();
            }

            sunsetUpdateOrderArrows($reorderNav);

            sunsetRefreshSocialValues();

        } );

        /**
         * Update order arrows
         */
        sunsetUpdateOrderArrows($reorderNav);

        /**
         * Apply sortable functionality to social items list
         */
        $( ".customizer-social-link-control-container > ul.ui-sortable" ).sortable({
            update: function( event, ui ) {
                sunsetRefreshSocialValues();
                sunsetUpdateOrderArrows($reorderNav);
            }
        });

        // Applies colorPicker for social icons
        applyColorPicker($('.customize-control-social-link-icon-color, .customize-control-social-link-icon-hover-color'));
        

        /**
         * TinyMCE Custom Control
         * https://aurooba.com/adding-tinymce-editor-in-wordpress-customizer/
         */
        function setupTinyMCE() {

            // Get the toolbar strings that were passed from the PHP Class
            let tinyMCEToolbar1 = _wpCustomizeSettings.controls[$( this ).attr( 'id' )].sunset_tinymce_toolbar1;
            let tinyMCEToolbar2 = _wpCustomizeSettings.controls[$( this ).attr( 'id' )].sunset_tinymce_toolbar2; // Get the media button condition passed from the PHP Class
            let tinyMCEMediaButtons = _wpCustomizeSettings.controls[$( this ).attr( 'id' )].sunset_tinymce_mediabuttons; // Get the editor height passed from the PHP Class
            let tinyMCEheight = _wpCustomizeSettings.controls[$( this ).attr('id')].sunset_tinymce_height; // Initialize editor with passed settings

            // initialize with unique ID (so you can have multiple) and with all the settings attributed correctly
            wp.editor.initialize( $( this ).attr( 'id' ), {
            tinymce: {
                wpautop: false,
                toolbar1: tinyMCEToolbar1,
                toolbar2: tinyMCEToolbar2,
                height: tinyMCEheight
            },
            quicktags: true,
            mediaButtons: tinyMCEMediaButtons
            });
        }
        
        /**
         * Init TinyMCE Editor
         * @param {*} event 
         * @param {HTMLCollection} editor jQuery textarea to which attach TinyMCE
         */
        function initTinyMCE(event, editor) {
            editor.on( 'change', function () {
                tinyMCE.triggerSave();
                $( "#".concat( editor.id ) ).trigger( 'change' );
            });
        }
    
        $( document ).on( 'tinymce-editor-init', initTinyMCE );
        $( '.customize-control-tinymce-editor' ).each( setupTinyMCE );

        // open General section
        $('a[href="#general-section"]').on('click', function(e){
            e.preventDefault();
            wp.customize.control( 'sunset_layout_width' ).focus();
        })

        /**
         * Handle Media upload button click
         */
        sunsetMediaUpload('.sunset-upload-media-button');

        /**
         * Handle Media delete button click
         */
        jQuery('body').on('click', '.sunset-delete-media-button', function (e) {
            e.preventDefault();
            $(this).closest('.customize-control').find('input:hidden').val('');
            $(this).closest('.customize-control').find('input:hidden').trigger('change');
            $(this).closest('.customize-control').find('img').attr('src', '');
            $(this).closest('.customize-control').find('img').attr('srcset', '');
            $(this).closest('.customize-control').find('img').hide();
            $(this).hide();
        });
    });
}) ( jQuery );