/**
 * @author 1902 Software
 * @copyright Copyright © 2023 1902 Software (https://1902software.com/magento/)
 * @package WriteTextAI_WriteTextAI
 */

define([
    'jquery',
    'uiComponent',
    'WriteTextAI_WriteTextAI/js/utils/edit/textfields',
    'mage/translate',
    'jquery/ui',
    'mage/mage',
    'mage/validation',
    'domReady!'
], function ($, Component, textFieldsUtils, $t) {
    'use strict';

    /**
     * @var {Component} self
     */
    var self;

    return Component.extend({
        defaults: {
            descMax: '',
            descMin: '',
            excMax: '',
            excMin: '',
            catDescMax: '',
            catDescMin: '',
            toneFieldsSelector: '[name="tones[]"]',
            styleFieldsSelector: '[name="styles"]',
            audienceFieldsSelector: '[name="audiences[]"]'
        },

        /** @inheritdoc */
        initialize: function () {
            this._super().observe([
                'descMax',
                'descMin',
                'excMax',
                'excMin',
                'catDescMax',
                'catDescMin'
            ]);

            this.initSpinner();
            this.initValidation();
            this.initSelectAll();
            this.initCombinations();

            const el = document.querySelector('.wtai-global-settings');
            if (el) {
                $('.wtai-global-settings > *').applyBindings(this);
            }

            self = this;
        },

        /**
         * Initialize combinations.
         */
        initCombinations: function () {
            setTimeout(function () {
                this.tonesCombination(null, true);
                this.stylesCombination(null, true);
                this.audiencesCombination(null, true);

                $(this.toneFieldsSelector).on("change", this.tonesCombination);
                $(this.styleFieldsSelector).on("change", this.stylesCombination);
                $(this.audienceFieldsSelector).on("change", function () {
                    this.audiencesCombination();
                    this.tonesCombination();
                    this.stylesCombination();
                }.bind(this));
            }.bind(this), 100);
        },
    
        /**
         * Validate combinations.
         *
         * @param {Object} event
         * @param {Boolean} onload
         *
         * @return {void}
         */
        tonesCombination: function (event = null, onload = false) {
            var value = [];

            $(self.toneFieldsSelector + ":checked").each(function () {
                value.push($(this).val());
            });

            if (!onload) {
                $(self.styleFieldsSelector).attr("disabled", false);
                $(self.audienceFieldsSelector).attr("disabled", false);
                $(self.styleFieldsSelector).siblings("div.wtai-disabled-tooltip").removeClass("wtai-active");
                $(self.audienceFieldsSelector).siblings("div.wtai-disabled-tooltip").removeClass("wtai-active");
                $(self.toneFieldsSelector).closest("div.wtai-field-column").removeAttr('title');
                $(self.styleFieldsSelector).closest("div.wtai-field-column").removeAttr('title');
                $(self.audienceFieldsSelector).closest("div.wtai-field-column").removeAttr('title');
            }

            for (var i = 0; i < self.disallowedCombinations.length; i++) {
                var currentCombination = self.disallowedCombinations[i].combination,
                    combination = currentCombination.find(function (obj) {
                        return obj.type == "Tone" && value.includes(obj.id);
                    });

                if (combination) {
                    var combinationStyle = currentCombination.find(function (obj) {
                            return obj.type == "Style";
                    }),
                        combinationAudience = currentCombination.find(function (obj) {
                            return obj.type == "Audience";
                        }),
                        styleFieldSelector = self.styleFieldsSelector + "[value=\"" + combinationStyle.id + "\"]";
                    
                    if (!combinationAudience) {
                        $(styleFieldSelector).attr("disabled", true);
                        self.processToolTip(styleFieldSelector, combination.id, combination.type);
                    } else {
                        var audienceFieldSelector = self.audienceFieldsSelector + "[value=\"" + combinationAudience.id + "\"]";

                        if ($(styleFieldSelector).is(":checked")) {
                            $(audienceFieldSelector).attr("disabled", true);
                        }
                        if ($(audienceFieldSelector).is(":selected")) {
                            $(styleFieldSelector).attr("disabled", true);
                        }
                    }
                }
            }
        },

        /**
         * Validate combinations.
         *
         * @param {Object} event
         * @param {Boolean} onload
         *
         * @return {void}
         */
        stylesCombination: function (event = null, onload = false) {
            var value = $(self.styleFieldsSelector + ":checked").val();

            if (!onload) {
                $(self.toneFieldsSelector).attr("disabled", false);
                $(self.audienceFieldsSelector).attr("disabled", false);
                $(self.toneFieldsSelector).siblings("div.wtai-disabled-tooltip").removeClass("wtai-active");
                $(self.audienceFieldsSelector).siblings("div.wtai-disabled-tooltip").removeClass("wtai-active");
                $(self.toneFieldsSelector).closest("div.wtai-field-column").removeAttr('title');
                $(self.audienceFieldsSelector).closest("div.wtai-field-column").removeAttr('title');
                $(self.styleFieldsSelector).closest("div.wtai-field-column").removeAttr('title');
            }

            for (var i = 0; i < self.disallowedCombinations.length; i++) {
                var currentCombination = self.disallowedCombinations[i].combination,
                    combination = currentCombination.find(function (obj) {
                        return obj.type == "Style" && obj.id == value;
                    });

                if (combination) {
                    var combinationTone = currentCombination.find(function (obj) {
                            return obj.type == "Tone";
                    }),
                        combinationAudience = currentCombination.find(function (obj) {
                            return obj.type == "Audience";
                        }),
                        toneFieldSelector = self.toneFieldsSelector + "[value=\"" + combinationTone.id + "\"]";

                    if (!combinationAudience) {
                        $(toneFieldSelector).attr("disabled", true);
                        self.processToolTip(toneFieldSelector, combination.id, combination.type);
                    } else {
                        var audienceFieldSelector = self.audienceFieldsSelector + "[value=\"" + combinationAudience.id + "\"]";

                        if ($(toneFieldSelector).is(":selected")) {
                            $(audienceFieldSelector).attr("disabled", true);
                        }
                        if ($(audienceFieldSelector).is(":selected")) {
                            $(toneFieldSelector).attr("disabled", true);
                        }
                    }
                }
            }
        },

        /**
         * Validate combinations.
         *
         * @param {Object} event
         * @param {Boolean} onload
         *
         * @return {void}
         */
        audiencesCombination: function (event = null, onload = false) {
            var value = [];

            $(self.audienceFieldsSelector + ":checked").each(function () {
                value.push($(this).val());
            });

            if (!onload) {
                $(self.toneFieldsSelector).attr("disabled", false);
                $(self.styleFieldsSelector).attr("disabled", false);
            }

            for (var i = 0; i < self.disallowedCombinations.length; i++) {
                var currentCombination = self.disallowedCombinations[i].combination,
                    combination = currentCombination.find(function (obj) {
                        return obj.type == "Audience" && obj.id == value;
                    });

                if (combination) {
                    var combinationTone = currentCombination.find(function (obj) {
                            return obj.type == "Tone";
                    }),
                        combinationStyle = currentCombination.find(function (obj) {
                            return obj.type == "Style";
                        }),
                        toneFieldSelector = self.toneFieldsSelector + "[value=\"" + combinationTone.id + "\"]",
                        styleFieldSelector = self.styleFieldsSelector + "[value=\"" + combinationStyle.id + "\"]";

                    if ($(toneFieldSelector).is(":selected")) {
                        $(styleFieldSelector).attr("disabled", true);
                    }
                    if ($(styleFieldSelector).is(":checked")) {
                        $(toneFieldSelector).attr("disabled", true);
                    }
                }
            }
        },

        /**
         * Validate min and max fields.
         *
         * @param {Object} data
         * @param {Object} event
         *
         * @return {void}
         */
        validateMinMax: function (data, event) {
            var target = event.target,
                value = Number(target.value),
                min = (target.getAttribute('min') === null || target.getAttribute('min') === '')
                    ? NaN
                    : Number(target.getAttribute('min')),
                max = (target.getAttribute('max') === null || target.getAttribute('max') === '')
                    ? NaN
                    : Number(target.getAttribute('max')),
                name = target.name;

            const mapping = {
                description_min: self.descMin,
                description_max: self.descMax,
                excerpt_min: self.excMin,
                excerpt_max: self.excMax,
                category_description_min: self.catDescMin,
                category_description_max: self.catDescMax
            };

            const GAP = 1;
            const clamp = function (num, minVal, maxVal) {
                if (!Number.isFinite(num)) {
                    return num;
                }

                if (Number.isFinite(minVal) && num < minVal) {
                    num = minVal;
                }
                if (Number.isFinite(maxVal) && num > maxVal) {
                    num = maxVal;
                }

                return num;
            };

            if (!Number.isFinite(value)) {
                return;
            }

            value = clamp(value, min, max);
            $(target).val(value);
            if (mapping[name]) {
                mapping[name](value);
            }

            const pairs = {
                description_min: 'description_max',
                description_max: 'description_min',
                excerpt_min: 'excerpt_max',
                excerpt_max: 'excerpt_min',
                category_description_min: 'category_description_max',
                category_description_max: 'category_description_min'
            };

            const partnerName = pairs[name];
            if (!partnerName) {
                return;
            }

            const partner = document.querySelector('[name="' + partnerName + '"]');
            if (!partner) {
                return;
            }

            var partnerValue = Number(partner.value),
                partnerMin = (partner.getAttribute('min') === null || partner.getAttribute('min') === '')
                    ? NaN
                    : Number(partner.getAttribute('min')),
                partnerMax = (partner.getAttribute('max') === null || partner.getAttribute('max') === '')
                    ? NaN
                    : Number(partner.getAttribute('max'));

            if (!Number.isFinite(partnerValue)) {
                partnerValue = value;
            }

            const isMinField = /_min$/.test(name);
            if (isMinField) {
                if (partnerValue < value + GAP) {
                    var newPartnerValue = clamp(value + GAP, partnerMin, partnerMax);

                    if (newPartnerValue < value + GAP && Number.isFinite(partnerMax)) {
                        value = clamp(partnerMax - GAP, min, max);
                        $(target).val(value);
                        if (mapping[name]) {
                            mapping[name](value);
                        }
                        newPartnerValue = clamp(value + GAP, partnerMin, partnerMax);
                    }

                    $(partner).val(newPartnerValue);
                    if (mapping[partnerName]) {
                        mapping[partnerName](newPartnerValue);
                    }
                }
            } else {
                if (partnerValue > value - GAP) {
                    var newPartnerValue = clamp(value - GAP, partnerMin, partnerMax);

                    if (newPartnerValue > value - GAP && Number.isFinite(partnerMin)) {
                        value = clamp(partnerMin + GAP, min, max);
                        $(target).val(value);
                        if (mapping[name]) {
                            mapping[name](value);
                        }
                        newPartnerValue = clamp(value - GAP, partnerMin, partnerMax);
                    }

                    $(partner).val(newPartnerValue);
                    if (mapping[partnerName]) {
                        mapping[partnerName](newPartnerValue);
                    }
                }
            }
        },

        /**
         * Initialize spinner.
         */
        initSpinner: function () {
            setTimeout(
                function () {
                    $('.wtai-global-settings .wtai-input-number:not(.wtai-setup-keywords-settings .wtai-input-number)').spinner({
                        numberFormat: 'n',
                        min: this.minOutputWords,
                        max: this.maxOutputWords
                    });
                }.bind(this),
                100
            );
        },

        /**
         * Initialize validation.
         */
        initValidation: function () {
            $('#wtaiStep3Form').mage('validation', {
                rules: {
                    'tones[]': { required: true },
                    styles: { required: true },
                    'product_texts[]': { required: true },
                    'category_texts[]': { required: true },
                    automatic_text_optimization: { required: true },
                    cluster_count: { required: true, number: true },
                    trigger_action_n_position: { required: true, number: true },
                    trigger_action_n_days: { required: true, number: true }
                },
                messages: {
                    'tones[]': {
                        required: $t('Please select at least one tone.')
                    }
                },
                errorPlacement: function (error, element) {
                    var parent = element.closest('.wtai-fieldset');

                    $(parent).find('.wtai-error-message').html(error);
                }
            });
        },

        /**
         * Process tooltip content
         *
         * @param {String} selector
         * @param {String} stringValue
         * @param {String} type
         *
         * @return {void}
         */
        processToolTip: function (selector, stringValue, type) {
            var textBase = '';
            switch (type) {
                case 'Tone':
                    textBase = $t("Unavailable when the '%1' tone is selected.");
                    break;
                case 'Style':
                    textBase = $t("Unavailable when the '%1' style is selected.");
                    break;
                default:
                    textBase = $t("Unavailable when the '%1' audience is selected.");
                    break;
            }

            var parentColumn = $(selector).closest('.wtai-field-column');
            if ($(selector).prop('disabled')) {
                parentColumn.attr('title', $t(textBase).replace('%1', stringValue));
            } else {
                parentColumn.removeAttr('title');
            }
        },

        /**
         * Validate number.
         *
         * @param {Object} data
         * @param {Object} event
         *
         * @return {Boolean}
         */
        ensureNumerical: function (data, event) {
            return textFieldsUtils.ensureNumerical(event.key);
        },

        /**
         * Initialize select all.
         */
        initSelectAll: function () {
            setTimeout(function () {
                var formSelector = '.wtai-fieldset.wtai-checkboxes',
                    selectAllSelector = '.wtai-checkbox-select-all',
                    dataNameAttribute = 'data-name';

                $(formSelector).each(function () {
                    var form = $(this),
                        fields = form.find('input[type="checkbox"]').not(selectAllSelector),
                        checkedFields = form.find('input[type="checkbox"]:checked').not(selectAllSelector)

                    if (fields.length === checkedFields.length) {
                        form.find(selectAllSelector).prop('checked', true);
                    } else {
                        form.find(selectAllSelector).prop('checked', false);
                    }

                    form.find(selectAllSelector).on('change', function () {
                        var name = $(this).attr(dataNameAttribute),
                            checked = $(this).prop('checked');

                        form.find('input[name="' + name + '[]"]:not(:disabled)').prop('checked', checked);

                        self.audiencesCombination();
                        self.tonesCombination();
                        self.stylesCombination();
                    });

                    form.find('input[type="checkbox"]')
                        .not(selectAllSelector)
                        .on('change', function () {
                            var name = $(this).attr('name'),
                                selector = form.find('input[name="' + name + '"]'),
                                selected = selector.filter(':checked').length,
                                identifier = name.replace('[]', '');

                            if (selected === selector.length) {
                                form.find('[' + dataNameAttribute + '="' + identifier + '"]').prop('checked', true);
                            } else {
                                form.find('[' + dataNameAttribute + '="' + identifier + '"]').prop('checked', false);
                            }
                        });
                });
            }, 100);
        }
    });
});
