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

define([
    'jquery',
    'underscore',
    'uiComponent',
    'ko',
    'WriteTextAI_WriteTextAI/js/model/edit',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/attributes',
    'WriteTextAI_WriteTextAI/js/model/edit/additional-prompt',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/textfields',
    'WriteTextAI_WriteTextAI/js/model/edit/product',
    'WriteTextAI_WriteTextAI/js/model/edit/audience',
    'WriteTextAI_WriteTextAI/js/model/edit/custom-tone-style',
    'WriteTextAI_WriteTextAI/js/model/edit/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/error-messages',
    'WriteTextAI_WriteTextAI/js/model/edit/mark-reviewed',
    'WriteTextAI_WriteTextAI/js/utils/edit/generate',
    'WriteTextAI_WriteTextAI/js/utils/edit/toolbar',
    'WriteTextAI_WriteTextAI/js/model/total-credits',
    'WriteTextAI_WriteTextAI/js/model/edit/preferences',
    'WriteTextAI_WriteTextAI/js/model/edit/gallery',
    'WriteTextAI_WriteTextAI/js/model/signalr',
    'WriteTextAI_WriteTextAI/js/model/edit/attributes',
    'WriteTextAI_WriteTextAI/js/model/edit/invalid-image-popup',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keywords',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/grid/popups/image-upload-progressbar',
    'WriteTextAI_WriteTextAI/js/model/edit/select-template',
    'Magento_Ui/js/modal/alert',
    'Magento_Ui/js/modal/confirm',
    'mage/translate',
    'collapsible',
    'accordion',
    'wtaiAdminIdle'
], function (
    $,
    _,
    Component,
    ko,
    editData,
    generateSettings,
    generateAttributes,
    additionalPrompt,
    genKeywordAnalysis,
    textfields,
    product,
    audience,
    customToneStyle,
    settings,
    errorMessagesModel,
    markReviewed,
    generateUtils,
    toolbarUtils,
    totalCredits,
    preferences,
    gallery,
    signalRModel,
    attributes,
    invalidImagePopupModel,
    keywordsData,
    keywordAnalysisData,
    imageUploadProgressbarModel,
    selectTemplateModel,
    alert,
    confirm,
    $t
) {
    'use strict';

    /**
     * @var {Component} self
     */
    var self;
    
    /**
     * @var {Component} self2
     */
    var self2 = {
        targetFieldId: null,
        targetFieldClass: null,
        generatedFieldId: null,
        generatedFieldIdSecondary: null,
        generatedOpenGraphEditor: null,
        generatedImageContainer: null,
        customPageTitle: null,
        customPageDescription: null,
        customProductDescription: null,
        customShortDescription: null,
        bulkGenerateImageContainer: null,
        baseUrl: null,
        activeGenerateRequest: null,  // Track active generate request
        activeUploadRequest: null,   // Track active upload request
        pendingRetryData: null       // Store data for retry
    };

    return Component.extend({
        defaults: {
            element: '.wtai-wtai-toolbar',
            collapsibleSelector: '.wtai-custom-action-select-wrap',
            toggleSelectAllSelector: 'input[name=select_all]',
            accordionTargetSelector: '.wtai-fieldset.wtai-text-editor',
            galleryAccordionSelector: '.wtai-gallery',
            accordionKeywordAttributesSelector: '.wtai-keywords-attributes',
            accordionToggleSelector: '.wtai-wtai-toolbar .wtai-toggle-accordion',
            accordionSingleToggleSelector:
                '.wtai-textfields .admin__collapsible-block-wrapper',
            accordionSelector: '.wtai-edit-modal-wrapper .wtai-accordions',
            textfieldsCount: 5,
            widgetsInitialized: false,
            suggestedAudience: [],
            selectedAudience: '',
            productId: '',
            storeId: '',
            tones: [],
            styles: [],
            audience: [],
            credits: [],
            tonesSelected: [],
            stylesSelected: '',
            audienceSelected: [],
            descMin: 0,
            descMax: 0,
            excMin: 0,
            excMax: 0,
            productAttributesSelected: [],
            otherProductDetails: '',
            otherProductDetailsChecked: false,
            additionalPrompt: '',
            selectedFields: [],
            customTone: '',
            customStyle: '',
            selectAllTonesValue: null,
            canUpdateTones: true,
            selectAllAudienceValue: null,
            canUpdateAudience: true,
            error: '',
            directiveRegex: [],
            customOpenGraph: false,
            formalLanguageSupport: [],
            formalLanguages: [],
            disallowedCombinations: [],
            highlightPronouns: false,
            language: '',
            defaultTones: [],
            defaultStyle: '',
            submitAction: 'generate',
            guideSteps: false,
            selectedImages: []
        },

        accordionExpanded: true,
        typingTimer: null,
        isTonesSelectedChanged: false,
        isHighlightPronounsChange: false,
        editToneStyleAllowed: false,
        isAudienceChange: false,
        selectedAudiencechanged: false,

        /** @inheritdoc */
        initialize: function () {
            this._super();

            self = this;
            self.initAjaxRetryHandler();

            self.submitAction.subscribe(function (submitAction) {
                settings.submitAction(submitAction);
            });

            gallery.selectedImages.subscribe(function (selectedImages) {
                self.selectedImages(selectedImages);
            });

            product.productId.subscribe(function (productId) {
                self.productId(productId);
            });

            product.storeId.subscribe(function (storeId) {
                self.storeId(storeId);
            });

            product.language.subscribe(function (language) {
                self.language(language);
            });

            product.directiveRegex.subscribe(function (directiveRegex) {
                if (directiveRegex && directiveRegex.length > 0) {
                    self.directiveRegex(directiveRegex);
                } else {
                    self.directiveRegex([]);
                }
            });

            self.selectedAudience.subscribe(function (selectedAudience) {
                if (!self.selectedAudiencechanged) {
                    audience.selectedAudience(selectedAudience);
                }
            });

            audience.selectedAudience.subscribe(function (selectedAudience) {
                self.selectedAudiencechanged = true;
                self.selectedAudience(selectedAudience);
                self.selectedAudiencechanged = false;
            });

            audience.suggestedAudience.subscribe(function (suggestedAudience) {
                self.suggestedAudience(suggestedAudience);
            });

            self.tonesSelected.subscribe(
                function (changes) {
                    if (!self.isTonesSelectedChanged) {
                        self.isTonesSelectedChanged = true;

                        _.each(changes, function (change) {
                            if (
                                change.status === 'added' &&
                                change.value === 'custom'
                            ) {
                                self.tonesSelected.remove(self.isNotCustom);
                                self.selectAllTonesValue(false);
                            }
                            if (
                                change.status === 'added' &&
                                change.value !== 'custom'
                            ) {
                                self.tonesSelected.remove('custom');
                                self.customTone('');
                            }
                        });

                        if (self.canUpdateTones) {
                            self.observeTonesSelected();
                        }

                        textfields.formal(
                            self.tonesSelected().indexOf('Formal') !== -1
                        );

                        self.isTonesSelectedChanged = false;
                    }
                    
                    preferences.tonesSelected(self.tonesSelected());
                },
                this,
                'arrayChange'
            );

            self.stylesSelected.subscribe(function (style) {
                if (style !== 'custom') {
                    self.customStyle('');
                }
                preferences.stylesSelected(style);
            });

            self.customTone.subscribe(function (customTone) {
                if (customTone) {
                    self.tonesSelected(['custom']);
                }
                preferences.customTone(customTone);
            });

            self.customStyle.subscribe(function (customStyle) {
                if (customStyle) {
                    self.stylesSelected('custom');
                }

                preferences.customStyle(customStyle);
            });

            self.highlightPronouns.subscribe(function (highlightPronouns) {
                if (!self.isHighlightPronounsChange) {
                    textfields.highlightPronouns(highlightPronouns);
                    self.saveHighlightPronouns(highlightPronouns);
                }
            });

            textfields.highlightPronouns.subscribe(
                function (highlightPronouns) {
                    self.isHighlightPronounsChange = true;
                    self.highlightPronouns(highlightPronouns);
                    self.isHighlightPronounsChange = false;
                }
            );

            customToneStyle.customTone.subscribe(function (customTone) {
                self.customTone(customTone);
            });

            customToneStyle.customStyle.subscribe(function (customStyle) {
                self.customStyle(customStyle);
            });

            textfields.selectedFields.subscribe(function (selectedFields) {
                self.selectedFields([]);
                for (let key in selectedFields) {
                    if (selectedFields.hasOwnProperty(key)) {
                        self.selectedFields.push(selectedFields[key]);
                    }
                }
            });

            generateSettings.descMin.subscribe(function (descMin) {
                self.descMin(descMin);
            });

            generateSettings.descMax.subscribe(function (descMax) {
                self.descMax(descMax);
            });

            generateSettings.excMin.subscribe(function (excMin) {
                self.excMin(excMin);
            });

            generateSettings.excMax.subscribe(function (excMax) {
                self.excMax(excMax);
            });

            generateAttributes.productAttributesSelected.subscribe(
                function (productAttributesSelected) {
                    self.productAttributesSelected([]);
                    for (let key in productAttributesSelected) {
                        if (productAttributesSelected.hasOwnProperty(key)) {
                            self.productAttributesSelected.push(
                                productAttributesSelected[key]
                            );
                        }
                    }
                }
            );

            generateAttributes.otherProductDetails.subscribe(
                function (otherProductDetails) {
                    self.otherProductDetails(otherProductDetails);
                }
            );

            generateAttributes.otherProductDetailsChecked.subscribe(
                function (otherProductDetailsChecked) {
                    self.otherProductDetailsChecked(otherProductDetailsChecked);
                }
            );

            additionalPrompt.promptValue.subscribe(
                function (additionalPrompt) {
                    self.additionalPrompt(additionalPrompt);
                }
            );

            editData.opened.subscribe(function (opened) {
                if (opened) {
                    /* reset generate/rewrite radio */
                    self.submitAction('generate');

                    /* reset accordions */
                    $(self.accordionKeywordAttributesSelector).accordion('activate', 0);
                    $(self.accordionKeywordAttributesSelector).accordion('activate', 1);
                    $(self.accordionSelector).each(function () {
                        if ($(this).hasClass('wtai-fieldset')) {
                            $(this).accordion('activate');
                        }
                    });
                }
                if (opened && !self.widgetsInitialized) {
                    self.bindCollapsible();
                    self.bindCheckboxToggle();
                    self.bindAccordionToggle();
                    self.widgetsInitialized = true;
                }
            });

            settings.tones.subscribe(function (tones) {
                var getTones = tones
                    .filter(function (tone) {
                        return tone.default;
                    })
                    .map(function (tone) {
                        return tone.id;
                    });

                self.tones(tones);
                if (getTones.length > 0) {
                    self.tonesSelected(getTones);
                }
            });

            settings.styles.subscribe(function (styles) {
                var getStyles = styles
                    .filter(function (style) {
                        return style.default;
                    })
                    .map(function (style) {
                        return style.id;
                    });

                self.styles(styles);
                if (getStyles.length > 0) {
                    self.stylesSelected(getStyles.shift());
                }
            });

            settings.audience.subscribe(function (settingsAudience) {
                var getAudience = settingsAudience
                    .filter(function (item) {
                        return item.default;
                    })
                    .map(function (item) {
                        return item.id;
                    });

                self.audience(settingsAudience);
                self.isAudienceChange = true;
                self.audienceSelected(getAudience);
                self.isAudienceChange = false;
            });

            settings.credits.subscribe(function (credits) {
                self.credits(credits);
            });

            settings.formalLanguageSupport.subscribe(
                function (formalLanguageSupport) {
                    self.formalLanguageSupport(formalLanguageSupport);
                }
            );

            settings.formalLanguages.subscribe(
                function (formalLanguages) {
                    self.formalLanguages(formalLanguages);
                }
            );

            settings.disallowedCombinations.subscribe(
                function (disallowedCombinations) {
                    self.disallowedCombinations(disallowedCombinations);
                }
            );
            
            settings.guideSteps.subscribe(function (guideSteps) {
                self.guideSteps(guideSteps);
            });

            self.audienceSelected.subscribe(function (audienceSelected) {
                if (self.canUpdateAudience) {
                    self.observeAudienceSelected();
                }
                preferences.audienceSelected(audienceSelected);
                if (!self.isAudienceChange) {
                    self.savePreferences('audiences', audienceSelected);
                }
            });
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super().observe([
                'suggestedAudience',
                'selectedAudience',
                'productId',
                'storeId',
                'tones',
                'styles',
                'audience',
                'credits',
                'tonesSelected',
                'stylesSelected',
                'audienceSelected',
                'descMin',
                'descMax',
                'excMin',
                'excMax',
                'productAttributesSelected',
                'otherProductDetails',
                'otherProductDetailsChecked',
                'additionalPrompt',
                'selectedFields',
                'customTone',
                'customStyle',
                'selectAllTonesValue',
                'selectAllAudienceValue',
                'error',
                'directiveRegex',
                'formalLanguageSupport',
                'formalLanguages',
                'disallowedCombinations',
                'highlightPronouns',
                'language',
                'submitAction',
                'guideSteps',
                'selectedImages'
            ]);

            this.keywords = ko.computed(function () {
                var optimizingKeywords = keywordAnalysisData.optimizationData().allOptimizingKeywords || [];
                
                if (optimizingKeywords && optimizingKeywords.length > 0) {
                    return optimizingKeywords;
                } else {
                    return keywordsData.selectedKeywords();
                }
            }, this);

            this.canGenerate = ko.computed(function () {
                var isProductOptimizing = Number(keywordAnalysisData.optimizingId()) === Number(this.productId()) &&
                        Number(keywordAnalysisData.optimizingStoreId()) === Number(this.storeId()),
                    keywordAnalysisOngoing = (keywordAnalysisData.optimizing() ||
                        keywordAnalysisData.isUploading()) &&
                        !keywordAnalysisData.optimized() &&
                        !keywordAnalysisData.optimizationFailed() &&
                        !keywordAnalysisData.imageUploadFailed();

                if (keywordAnalysisOngoing && isProductOptimizing) {
                    return false;
                }

                var canGenerateFields = this.selectedFields() ? this.selectedFields().length > 0 : false,
                    canGenerateMedia = this.selectedImages() ? this.selectedImages().length > 0 : false;

                if (this.submitAction() === 'rewrite') {
                    return canGenerateFields;
                } else {
                    return canGenerateFields || canGenerateMedia;
                }
            }, this);

            this.selectedFieldsCount = ko.computed(function () {
                if (gallery.images().length > 0) {
                    return this.selectedFields().length === this.textfieldsCount && gallery.selectAllImages();
                } else {
                    return this.selectedFields().length === this.textfieldsCount;
                }
            }, this);

            this.getTonesStylesSelected = ko.computed(function () {
                var tonesCount = this.tonesSelected() ? this.tonesSelected().length : 0,
                    stylesCount = this.stylesSelected() ? 1 : 0,
                    total = tonesCount + stylesCount;

                return total + ' ' + $t('selected');
            }, this);

            this.getAudienceSelected = ko.computed(function () {
                var audienceCount = this.audienceSelected() ? this.audienceSelected().length : 0;

                return audienceCount + ' ' + $t('selected');
            }, this);

            /**
             * Check if rewrite is available.
             */
            this.rewriteAvailable = ko.computed(function () {
                var isProductOptimizing = Number(keywordAnalysisData.optimizingId()) === Number(this.productId()) &&
                    Number(keywordAnalysisData.optimizingStoreId()) === Number(this.storeId()),
                keywordAnalysisOngoing = (keywordAnalysisData.optimizing() ||
                    keywordAnalysisData.isUploading()) &&
                    !keywordAnalysisData.optimized() &&
                    !keywordAnalysisData.optimizationFailed() &&
                    !keywordAnalysisData.imageUploadFailed();

                if (keywordAnalysisOngoing && isProductOptimizing) {
                    return false;
                }

                var selectedFields = this.selectedFields(),
                    selectedImages = this.selectedImages(),
                    textFields = textfields,
                    images = gallery.images();
    
                var canRewriteFields = selectedFields.some((field) => {
                        return (
                            field === 'page_title' &&
                                textFields.mgPageTitle() !== '' ||
                            field === 'page_description' &&
                                textFields.mgPageDescription() !== '' ||
                            field === 'product_description' &&
                                textFields.mgProductDescription() !== '' ||
                            field === 'short_product_description' &&
                                textFields.mgProductShortDescription() !== '' ||
                            self.customOpenGraph &&
                                field === 'open_graph' &&
                                textFields.mgOpenGraph() !== ''
                        );
                    }),
                    canRewriteMedia = images.some((image) => {
                        return image.alt !== '' && selectedImages.includes(image.id)
                    });

                return canRewriteFields || canRewriteMedia;
            }, this);

            this.enableHighlightPronouns = ko.computed(function () {
                return this.tonesSelected().indexOf('Formal') !== -1;
            }, this);

            return this;
        },

        /**
         * Save user preferences for tones and styles
         */
        saveTonesAndStyles: function () {
            var url = self.saveUrl,
                tones = self.tonesSelected(),
                customTone = self.customTone(),
                styles = self.stylesSelected(),
                customStyle = self.customStyle();
            
            if (tones.length <= 0) {
                tones = '';
            }

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    tones: tones,
                    style: styles,
                    custom_tone: customTone,
                    custom_style: customStyle,
                    entity_type: '',
                    scope: ''
                },
                dataType: 'json',
                showWriteTextAILoader: false,
                success: function (response) {
                    if (!response.success) {
                        console.log(response);
                    }
                }
            });
        },

        /**
         * Initialize AJAX retry handler for _generate function only
         */
        initAjaxRetryHandler: function() {
            // Listen for admin-idle.js events
            $(document).on('wtai:user-return', function() {
                console.log('WriteText.ai: User returned, checking for interrupted generation');
                self.checkAndRetryGenerate();
            });
            
            // Also use Page Visibility API as backup
            document.addEventListener('visibilitychange', function() {
                if (!document.hidden) {
                    console.log('WriteText.ai: Page became visible');
                    setTimeout(function() {
                        self.checkAndRetryGenerate();
                    }, 500);
                }
            });
            
            // Handle focus event for additional reliability on tablets
            window.addEventListener('focus', function() {
                setTimeout(function() {
                    self.checkAndRetryGenerate();
                }, 500);
            });
        },
        
        /**
         * Check for interrupted generate and upload requests and retry
         */
        checkAndRetryGenerate: function() {
            // Check if we have pending retry data
            if (self2.pendingRetryData) {
                console.log('WriteText.ai: Retrying interrupted request');
                var retryData = self2.pendingRetryData;
                self2.pendingRetryData = null;
                
                if (retryData.type === 'upload') {
                    // Check if upload is still needed
                    if (imageUploadProgressbarModel && imageUploadProgressbarModel.visible()) {
                        console.log('WriteText.ai: Retrying upload from index', retryData.index);
                        self.uploadRequest(
                            retryData.data, 
                            retryData.params, 
                            retryData.imageChunks, 
                            retryData.index, 
                            retryData.keywordAnalysis
                        );
                    } else {
                        console.log('WriteText.ai: Upload no longer active, skipping retry');
                    }
                } else {
                    // Check if generation is still needed
                    if (signalRModel && signalRModel.generating && signalRModel.generating()) {
                        self._generate(retryData.data, retryData.keyword_analysis ?? false);
                    } else {
                        console.log('WriteText.ai: Generation no longer active, skipping retry');
                    }
                }
            }
            
            // Check if generate request is stuck
            if (self2.activeGenerateRequest) {
                var now = Date.now();
                var duration = now - self2.activeGenerateRequest.startTime;
                
                // If request has been running for more than 60 seconds, retry
                if (duration > 60000) {
                    console.log('WriteText.ai: Generate request appears stuck, retrying');
                    
                    // Abort if possible
                    if (self2.activeGenerateRequest.jqXHR && self2.activeGenerateRequest.jqXHR.abort) {
                        self2.activeGenerateRequest.jqXHR.abort();
                    }
                    
                    // Store for retry
                    self2.pendingRetryData = {
                        type: 'generate',
                        url: self2.activeGenerateRequest.url,
                        data: self2.activeGenerateRequest.data
                    };
                    
                    self2.activeGenerateRequest = null;
                    
                    // Retry
                    self.checkAndRetryGenerate();
                }
            }
            
            // Check if upload request is stuck
            if (self2.activeUploadRequest) {
                var now = Date.now();
                var duration = now - self2.activeUploadRequest.startTime;
                
                // If request has been running for more than 60 seconds, retry
                if (duration > 60000) {
                    console.log('WriteText.ai: Upload request appears stuck, retrying');
                    
                    // Abort if possible
                    if (self2.activeUploadRequest.jqXHR && self2.activeUploadRequest.jqXHR.abort) {
                        self2.activeUploadRequest.jqXHR.abort();
                    }
                    
                    // Store for retry
                    self2.pendingRetryData = {
                        type: 'upload',
                        data: self2.activeUploadRequest.data,
                        params: self2.activeUploadRequest.params,
                        imageChunks: self2.activeUploadRequest.imageChunks,
                        index: self2.activeUploadRequest.index,
                        keywordAnalysis: self2.activeUploadRequest.keywordAnalysis
                    };
                    
                    self2.activeUploadRequest = null;
                    
                    // Retry
                    self.checkAndRetryGenerate();
                }
            }
        },

        /**
         * Handle custom tone and style typing
         */
        handleCustomToneStyle: function () {
            clearTimeout(self.typingTimer);

            self.typingTimer = setTimeout(function () {
                self.saveTonesAndStyles();
            }, 2000);
        },

        /**
         * Save user preferences
         *
         * @param {string} field
         * @param {string} selected
         * @param {string} entityType
         * @param {string} scope
         *
         * @returns {void}
         */
        savePreferences: function (field, selected, entityType = '', scope = '') {
            var value = selected;
            
            if (value.length <= 0) {
                value = '';
            }
            
            $.ajax({
                url: self.saveUrl,
                type: 'POST',
                data: {
                    [field]: value,
                    entity_type: entityType,
                    scope: scope
                },
                dataType: 'json',
                showLoader: false,
                success: function (response) {
                    if (!response.success) {
                        console.log(response);
                    }
                }
            });
        },

        /**
         * Process click functionality of select all
         * Important to always return true
         * in order for checked binding to continue working
         *
         * @returns {boolean}
         */
        processClick: function () {
            var value = gallery.selectAllImages();
            self.savePreferences('gallery', !value, 'product', 'edit');
            return true;
        },

        /**
         * Check if not custom
         *
         * @param {string} value
         * @returns {boolean}
         */
        isNotCustom: function (value) {
            return value !== 'custom';
        },

        /**
         * Save user settings for highlighted pronouns.
         *
         * @param {boolean} highlighted
         * @returns {void}
         */
        saveHighlightPronouns: function (highlighted) {
            $.ajax({
                url: self.highlightPronounsUrl,
                type: 'POST',
                data: {
                    highlighted: highlighted,
                    entity_type: 'product'
                },
                dataType: 'json',
                showWriteTextAILoader: false,
                success: function (response) {
                    if (!response.success) {
                        console.log(response.message);
                    }
                }
            });
        },

        /**
         * Get tooltip text based on disallowed combination
         *
         * @param {string} id
         * @param {string} type
         *
         * @returns {string}
         */
        getToolTipCombinationDisallowed: function (id, type) {
            if (this.isCombinationDisallowed(id, type)) {
                return this.getTooltipCombinationDisallowedText(id, type);
            }
            return '';
        },

        /**
         * Check if combination is not allowed
         *
         * @param {string} id
         * @param {string} type
         *
         * @returns {boolean}
         */
        isCombinationDisallowed: function (id, type) {
            return toolbarUtils.isCombinationDisallowed(id, type, self);
        },

        /**
         * Get tooltip text based on disallowed combination
         *
         * @param {string} id
         * @param {string} type
         *
         * @returns {string}
         */
        getTooltipCombinationDisallowedText: function (id, type) {
            return toolbarUtils.getTooltipCombinationDisallowedText(id, type, self);
        },

        /**
         * Get custom style length.
         */
        getCustomStyleLength: function () {
            var length = this.customStyle() ? this.customStyle().length : 0;

            return (
                length + '/' + this.rules.maxCustomStyleLength + ' ' + $t('Char')
            );
        },

        /**
         * Get custom tone length.
         */
        getCustomToneLength: function () {
            var length = this.customTone() ? this.customTone().length : 0;

            return length + '/' + this.rules.maxCustomToneLength + ' ' + $t('Char');
        },

        /**
         * Get custom tone length.
         */
        getCustomAudienceLength: function () {
            var length = this.selectedAudience()
                ? this.selectedAudience().length
                : 0;

            return (
                length + '/' + this.rules.maxCustomAudienceLength + ' ' + $t('Char')
            );
        },

        /**
         * Bind settings dropdown toggle.
         */
        bindCollapsible: function () {
            toolbarUtils.bindCollapsible();
        },

        /**
         * Bind select text fields checkbox toggle.
         */
        bindCheckboxToggle: function () {
            var fields = [
                    'page_title',
                    'page_description',
                    'product_description',
                    'short_product_description'
                ],
                fieldsCopy = [];

            if (self.customOpenGraph) {
                fields.push('open_graph');
            }

            fieldsCopy = [...fields];

            $(self.toggleSelectAllSelector).on('click', function () {
                var value = [];

                if (this.checked) {
                    value = Object.keys(fieldsCopy)
                        .filter(key => fieldsCopy.hasOwnProperty(key))
                        .map(key => fieldsCopy[key]);
                }

                textfields.selectedFields(value);
                gallery.selectAllImages(this.checked);
                self.savePreferences('single_editor', value, 'product', 'edit');
                
            });
        },

        /**
         * Bind text field accordion toggle.
         */
        bindAccordionToggle: function () {
            $(self.accordionToggleSelector).on('click', function () {
                if (self.accordionExpanded) {
                    $(self.accordionTargetSelector).accordion('deactivate');
                    $(self.accordionKeywordAttributesSelector).accordion('deactivate');
                    $(self.galleryAccordionSelector).accordion('deactivate');
                    self.accordionExpanded = false;
                } else {
                    $(self.accordionTargetSelector).accordion('activate');
                    $(self.accordionKeywordAttributesSelector).accordion('activate');
                    $(self.galleryAccordionSelector).accordion('activate');
                    self.accordionExpanded = true;
                }
            });
        },

        /**
         * Handle input custom audience.
         */
        handleInputAudience: function () {
            clearTimeout(self.typingTimer);

            self.typingTimer = setTimeout(function () {
                self.selectAudience();
            }, 2000);
        },

        /**
         * Regenerate suggested audience.
         */
        getAudience: function () {
            var url = self.audienceGetUrl,
                storeId = self.storeId(),
                productId = self.productId();

            self.selectedAudience('');
            self.suggestedAudience('');

            errorMessagesModel.messages([]);

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    product_id: productId,
                    store_id: storeId,
                    keywords: self.keywords(),
                    product_name: product.productName()
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showAudienceLoader: true,
                success: function (response) {
                    if (response.success) {
                        self.selectedAudience(response.selected.shift());
                        self.suggestedAudience(response.values);
                    } else {
                        errorMessagesModel.messages.push(response.message);
                    }
                }
            });
        },

        /**
         * Select a suggested audience.
         *
         * @param {string} selected
         * @return void
         */
        selectAudience: function (selected = null) {
            var url = self.audienceSelectUrl,
                storeId = self.storeId(),
                productId = self.productId(),
                productName = product.productName();

            selected = selected || self.selectedAudience();
            
            errorMessagesModel.messages([]);

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    product_id: productId,
                    store_id: storeId,
                    selected: selected,
                    product_name: productName
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showAudienceLoader: true,
                success: function (response) {
                    if (response.success) {
                        self.selectedAudience(response.selected.shift());
                        self.suggestedAudience(response.values);
                    } else {
                        errorMessagesModel.messages.push(response.message);
                    }
                }
            });
        },

        /**
         * Generate selected text fields.
         *
         * @param {boolean} rewrite
         * @param {boolean} keywordAnalysis
         *
         * @returns {void}
         */
        generate: function (rewrite = false, keywordAnalysis = false) {
            var selectedFields = self.selectedFields();

            let isAnyFieldModified = false;

            const fieldsToCheck = [
                {
                    field: 'page_title',
                    getter: () =>
                        textfields.originalPageTitle() !==
                        textfields.pageTitle()
            }, {
                field: 'page_description',
                getter: () =>
                    textfields.originalPageDescription() !==
                    textfields.pageDescription()
            }, {
                field: 'product_description',
                getter: () =>
                    textfields.originalProductDescription() !==
                    textfields.productDescription()
            }, {
                field: 'short_product_description',
                getter: () =>
                    textfields.originalProductShortDescription() !==
                    textfields.productShortDescription()
            }, {
                field: 'open_graph',
                getter: () =>
                    textfields.originalOpenGraph() !==
                    textfields.openGraph()
            }
            ];

            for (const field of fieldsToCheck) {
                if (selectedFields.includes(field.field) && field.getter()) {
                    isAnyFieldModified = true;
                    break;
                }
            }

            for (const image of gallery.images()) {
                if (
                    gallery.selectedImages().includes(image.id) &&
                    image.original_writetext_alt !== image.writetext_alt
                ) {
                    isAnyFieldModified = true;
                    break;
                }
            }

            if (isAnyFieldModified) {
                confirm({
                    /* eslint-disable-next-line max-len */
                    content: $t('You have unsaved changes. Are you sure you want to regenerate and replace text?'),
                    buttons: [{
                        text: $t('Cancel'),
                        class: 'action-secondary action-dismiss',
                        click: function (event) {
                            keywordsData.showProgress(false);
                            keywordAnalysisData.isUploading(false);
                            keywordAnalysisData.optimizing(false);
                            this.closeModal(event);
                        }
                    }, {
                        text: $t('Ok'),
                        class: 'action-primary action-accept',
                        click: function (event) {
                            this.closeModal(event, true);
                            self.generateAction(rewrite, keywordAnalysis);
                        }
                    }]
                });
            } else {
                self.generateAction(rewrite, keywordAnalysis);
            }
        },

        /**
         * Generate selected text fields.
         *
         * @param {boolean} rewrite
         * @param {boolean} keywordAnalysis
         *
         * @returns {void}
         */
        generateAction: function (rewrite = false, keywordAnalysis = false) {
            
            var tones = self.tonesSelected(),
                styles = self.stylesSelected(),
                audienceSelected = self.audienceSelected(),
                storeId = self.storeId(),
                productId = self.productId(),
                descMin = self.descMin(),
                descMax = self.descMax(),
                excMin = self.excMin(),
                excMax = self.excMax(),
                productAttributes = attributes.productAttributes(),
                productAttributesSelected = self.productAttributesSelected(),
                otherProductDetails = self.otherProductDetails(),
                otherProductDetailsChecked = self.otherProductDetailsChecked(),
                additionalPrompt = self.additionalPrompt(),
                selectedFields = self.selectedFields(),
                selectedImages = self.selectedImages(),
                images = gallery.images(),
                customTone = self.customTone(),
                customStyle = self.customStyle(),
                customAudience = self.selectedAudience(),
                keywordAnalysisViews = genKeywordAnalysis.views(),
                keywords = self.keywords(),
                data = {
                    tones: tones,
                    styles: styles,
                    audience: audienceSelected,
                    custom_audience: customAudience,
                    store_id: storeId,
                    product_id: productId,
                    desc_min: descMin,
                    desc_max: descMax,
                    exc_min: excMin,
                    exc_max: excMax,
                    product_attributes: productAttributes,
                    product_attributes_selected: productAttributesSelected,
                    selected_fields: selectedFields,
                    rewrite: rewrite,
                    keyword_analysis_views: keywordAnalysisViews,
                    selected_images: selectedImages,
                    images: images,
                    keywords: keywords,
                    search_intent_selected: keywordsData.searchIntentSelected(),
                    gallery_images: [],
                    templates_used: selectTemplateModel.selectedTemplates
            };

            if (keywordAnalysis) {
                data.keyword_analysis = keywordAnalysis;
            }

            if (!this.isCheckboxesValid()) {
                keywordsData.showProgress(false);
                keywordAnalysisData.isUploading(false);
                keywordAnalysisData.optimizing(false);
                alert({
                    content: this.error()
                });
                return;
            }

            if (otherProductDetailsChecked) {
                data.other_product_details = otherProductDetails;
            }
            if (additionalPrompt) {
                data.additional_prompt = additionalPrompt;
            }
            if (tones.indexOf('custom') !== -1) {
                data.custom_tone = customTone;
            }
            if (styles === 'custom') {
                data.custom_style = customStyle;
            }

            if (rewrite && this.hasMediaOrDirective()) {
                confirm({
                    title: $.mage.__('Rewrite selected'),
                    /* eslint-disable-next-line max-len */
                    content: $.mage.__('Note: Any media or directive you have inserted into the existing text will not be included in the rewritten version. The language of the text you are rewriting will be the same language used in the output.'),
                    actions: {
                        confirm: function () {
                            self._generate(data, keywordAnalysis);
                        },
                        cancel: function () {
                            keywordsData.showProgress(false);
                            keywordAnalysisData.isUploading(false);
                            keywordAnalysisData.optimizing(false);
                            return;
                        }
                    }
                });
            } else {
                var imageSelected = this.selectedImages() ? this.selectedImages().length > 0 : false;

                var galleryToUpload = false;
                if (images.length > 0 &&
                    (data.selected_fields.includes('product_description') ||
                    data.selected_fields.includes('short_product_description'))
                ) {
                    var allGalleryImageIds = images.map(function (image) {
                        return image.id;
                    });
                    galleryToUpload = allGalleryImageIds.length > 0;
                    if (galleryToUpload) {
                        data.gallery_images = allGalleryImageIds;
                    }
                }

                var thumbnail = data.product_attributes.find(
                    function (attr) {
                        return attr.attribute_code === 'thumbnail';
                    }
                );
                
                var thumbnailSelected = thumbnail && data.product_attributes_selected.includes('thumbnail') ? true : false;

                gallery.failedImages([]);
                gallery.failedImagesWithoutThumbnail([]);
                gallery.successImages([]);
                gallery.invalid([]);
                gallery.notSupported([]);
                gallery.downloadFailed([]);
                gallery.general([]);
                gallery.errorMessages([]);
                if (galleryToUpload || imageSelected || thumbnailSelected || keywordAnalysis) {
                    if (!keywordAnalysis) {
                        imageUploadProgressbarModel.visible(true);
                        imageUploadProgressbarModel.toCancel(false);
                        imageUploadProgressbarModel.progress(0);
                    }
                    self.uploadImages(data, keywordAnalysis);
                } else {
                    self._generate(data);
                }
            }
        },

        /**
         * Upload images
         *
         * @param {Object} data
         * @returns {void}
         */
        uploadImages: function (data, keywordAnalysis = false) {
            var params = {
                store_id: data.store_id,
                product_id: data.product_id,
                selected_images: data.selected_images,
                images: data.images,
                selected_fields: data.selected_fields,
                gallery_images: data.gallery_images
            };

            if (data.selected_fields.length > 0 || keywordAnalysis) {
                params.product_attributes_selected = data.product_attributes_selected;
                params.product_attributes = data.product_attributes;
            }

            errorMessagesModel.messages([]);
            /* gallery.failedImages([]);
            gallery.failedImagesWithoutThumbnail([]); */
            gallery.successImages([]);
            gallery.proceedable(false);
            /** Collect all images first, then split into chunks of 10 */
            var allImages = [];

            if ((params.product_attributes_selected && params.product_attributes_selected.includes('thumbnail')) || keywordAnalysis) {
                var thumbnail = params.product_attributes.find(
                    function (attr) {
                        return attr.attribute_code === 'thumbnail';
                    }
                );
                if (thumbnail) {
                    allImages.push(thumbnail.value);
                }
            }

            if (data.selected_fields.includes('product_description') ||
                data.selected_fields.includes('short_product_description')
            ) {
                if (data.gallery_images.length > 0) {
                    allImages = allImages.concat(data.gallery_images);
                }
            } else {
                if (data.selected_images.length > 0) {
                    allImages = allImages.concat(data.selected_images);
                }
            }

            /** Remove duplicates from collected images */
            allImages = [...new Set(allImages)];
            
            /** Split all collected images into chunks of 10 */
            var imageChunks = [];
            for (var i = 0; i < allImages.length; i += 10) {
                imageChunks.push(allImages.slice(i, i + 10));
            }

            imageUploadProgressbarModel.total(imageChunks.reduce(function (total, chunk) {
                return total + chunk.length;
            }, 0));

            /** Start uploading the first chunk */
            self.uploadRequest(data, params, imageChunks, 0, keywordAnalysis);
        },

        /**
         * Upload images request
         *
         * @param {Object} data
         * @param {Object} params
         * @param {Array} imageChunks
         * @param {Number} index
         * @param {boolean} keywordAnalysis
         *
         * @returns {void}
         */
        uploadRequest: function (data, params, imageChunks, index, keywordAnalysis = false) {
            keywordAnalysisData.imageUploadFailed(false);
            if (keywordAnalysis) {
                keywordAnalysisData.isUploading(true);
            }

            if (imageUploadProgressbarModel.toCancel()) {
                imageUploadProgressbarModel.visible(false);
                return;
            }

            var errorMessages = gallery.errorMessages();
            if (index < imageChunks.length) {
                /** Add images to params */
                /** params.selected_images = imageChunks[index]; */
                params.gallery_images = imageChunks[index];

                // Track active upload request for retry mechanism
                self2.activeUploadRequest = {
                    url: self.uploadImagesUrl,
                    data: data,
                    params: params,
                    imageChunks: imageChunks,
                    index: index,
                    keywordAnalysis: keywordAnalysis,
                    startTime: Date.now()
                };

                var ajaxRequest = $.ajax({
                    url: self.uploadImagesUrl,
                    type: 'POST',
                    data: params,
                    dataType: 'json',
                    showWriteTextAILoader: true,
                    showGalleryLoader: true,
                    success: function (response) {
                        /* Clear active upload request */
                        self2.activeUploadRequest = null;
                        
                        if (!response.success) {
                            if (response.unauthorized) {
                                window.location.href = response.login_url;
                            }

                            if (response.failed_images) {
                                gallery.failedImages.push(...response.failed_images);
                                gallery.failedImagesWithoutThumbnail.push(...response.failed_images_without_thumbnail);
                                gallery.successImages.push(...response.success_images);
                                gallery.invalid.push(...response.invalid);
                                gallery.notSupported.push(...response.not_supported);
                                gallery.downloadFailed.push(...response.download_failed);
                                gallery.general.push(...response.general);
                                gallery.errorMessages({...errorMessages, ...response.error_messages});

                                if (response.proceedable || keywordAnalysis) {
                                    gallery.proceedable(true);
                                }
                            } else {
                                if (response.message) {
                                    errorMessagesModel.messages.push(response.message);
                                }
                                imageUploadProgressbarModel.visible(false);
                                return;
                            }

                            
                        } else {
                            imageUploadProgressbarModel.progress(
                                imageChunks
                                    .slice(0, index + 1)
                                    .reduce((total, chunk) => total + chunk.length, 0)
                            );

                        }

                        /** Upload next chunk */
                        self.uploadRequest(data, params, imageChunks, index + 1, keywordAnalysis);
                    },
                    error: function (xhr, status, error) {
                        /* Clear active upload request */
                        self2.activeUploadRequest = null;
                        
                        /* Check if this was due to page being backgrounded */
                        if (status === 'abort' || (xhr && xhr.readyState === 0)) {
                            console.log('WriteText.ai: Upload request interrupted, will retry on page focus');
                            /* Store for retry */
                            self2.pendingRetryData = {
                                type: 'upload',
                                data: data,
                                params: params,
                                imageChunks: imageChunks,
                                index: index,
                                keywordAnalysis: keywordAnalysis
                            };
                        } else {
                            /* Normal error handling */
                            keywordAnalysisData.imageUploadFailed(true);
                            errorMessagesModel.messages.push($t('Image upload failed. Please try again.'));
                        }
                    }
                });
                
                /* Store the jqXHR object for potential abort */
                if (self2.activeUploadRequest) {
                    self2.activeUploadRequest.jqXHR = ajaxRequest;
                }
            } else {
                imageUploadProgressbarModel.visible(false);

                if (gallery.failedImages().length <= 0) {
                    self._generate(data, keywordAnalysis);
                } else {
                    if (keywordAnalysis) {
                        keywordAnalysisData.imageUploadFailed(true);
                    }
                    invalidImagePopupModel.data({});
                    
                    if (gallery.proceedable()) {
                        invalidImagePopupModel.data(data);
                        invalidImagePopupModel.keywordAnalysis(keywordAnalysis);
                        if (data.selected_images.length > 0) {
                            data.selected_images = data.selected_images.filter(function (image) {
                                return gallery.successImages().includes(image);
                            });
                        }
                        data.gallery_images = gallery.successImages();
                        keywordsData.showProgress(false);
                    }

                    $('.wtai-invalid-image-popup').modal('openModal');
                }

                keywordAnalysisData.customProgressText($t('Initializing...'));
                keywordAnalysisData.isUploading(false);
            }
        },

        /**
         * Generate selected text fields.
         *
         * @param {Object} data
         * @returns {void}
         */
        _generate: function (data, keywordAnalysis = false) {
            /**clear error */
            $('body').notification('clear');

            var url = self.generateUrl;

            if (keywordAnalysis) {
                keywordsData.showProgress(true);
            }

            /**
            if (data.gallery_images.length > 0) {
                data.selected_images = data.selected_images.filter(function(image) {
                    return data.gallery_images.includes(image);
                });
            }
            */

            /* close dropdown */
            $(self.collapsibleSelector + '.submit').collapsible('deactivate');

            /* do not rewrite empty fields */
            if (data.rewrite) {
                data.selected_fields = generateUtils.removeEmptyFields(
                    data.selected_fields
                );

                if (data.selected_images && data.selected_images.length > 0) {
                    data.selected_images = generateUtils.removeImageWithEmptyAlt(
                        data.selected_images
                    );
                }
            }

            if (keywordAnalysis && generateUtils.checkIfFieldsAndImagesAreEmpty(data)) {
                keywordsData.noGenerateOnAutoGenerateAfterKo(true);
                generateUtils.requestKeywordAnalysis(self.updateOptimizationUrl, 'Product');
                return;
            }

            /* empty text fields */
            generateUtils.clearFields(data.selected_fields, data.selected_images);

            /* remove error messages */
            errorMessagesModel.messages([]);
            
            // Track active generate request for retry mechanism
            self2.activeGenerateRequest = {
                url: url,
                data: data,
                startTime: Date.now()
            };
            
            var ajaxRequest = $.ajax({
                url: url,
                type: 'POST',
                data: data,
                dataType: 'json',
                showWriteTextAILoader: true,
                showPageTitleLoader: data.selected_fields.includes('page_title'),
                showPageDescriptionLoader: data.selected_fields.includes('page_description'),
                showProductDescriptionLoader: data.selected_fields.includes('product_description'),
                showShortDescriptionLoader: data.selected_fields.includes('short_product_description'),
                showOpenGraphLoader: data.selected_fields.includes('open_graph'),
                showGalleryLoader: data.selected_images ? data.selected_images.length > 0 : false,
                success: function (response) {
                    /* Clear active request */
                    self2.activeGenerateRequest = null;
                    
                    if (response.success) {
                        markReviewed.reviewed(response.reviewed);
                        genKeywordAnalysis.views(0);
                    } else {
                        keywordAnalysisData.optimizationFailed(true);
                        keywordAnalysisData.optimizing(false);
                        keywordsData.showProgress(false);
                        self.getGenerated(data.selected_fields, data.selected_images);
                        if (response.message) {
                            errorMessagesModel.messages.push(response.message);
                        }
                        signalRModel.generating(false);
                        generateUtils.removeIdentifierFromCurrentlyGeneratingRecordIdentifiers('Product');

                        if (response.unauthorized) {
                            window.location.href = response.login_url;
                        }
                    }
                },
                error: function(xhr, status, error) {

                    /* Clear active request */
                    self2.activeGenerateRequest = null;
                    
                    /* Check if this was due to page being backgrounded */
                    if (status === 'abort' || (xhr && xhr.readyState === 0)) {
                        console.log('WriteText.ai: Generate request interrupted, will retry on page focus');
                        /* Store for retry */
                        self2.pendingRetryData = {
                            url: url,
                            data: data
                        };
                    } else {
                        /* Normal error handling */
                        errorMessagesModel.messages.push($t('An error occurred while generating content. Please try again.'));
                        signalRModel.generating(false);
                        generateUtils.removeIdentifierFromCurrentlyGeneratingRecordIdentifiers('Product');
                    }
                }
            });
            
            /* Store the jqXHR object for potential abort */
            if (self2.activeGenerateRequest) {
                self2.activeGenerateRequest.jqXHR = ajaxRequest;
            }
        },

        /**
         * Get generated text fields.
         *
         * @param {Array} selectedFields
         * @param {Array} selectedImages
         *
         * @returns {void}
         */
        getGenerated: function (selectedFields, selectedImages) {
            var url = self.getGeneratedUrl,
                productId = self.productId(),
                storeId = self.storeId();

            errorMessagesModel.messages([]);

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    product_id: productId,
                    store_id: storeId
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showPageTitleLoader: selectedFields.includes('page_title'),
                showPageDescriptionLoader: selectedFields.includes('page_description'),
                showProductDescriptionLoader: selectedFields.includes('product_description'),
                showShortDescriptionLoader: selectedFields.includes('short_product_description'),
                showOpenGraphLoader: selectedFields.includes('open_graph'),
                showGalleryLoader: selectedImages ? selectedImages.length > 0 : false,
                success: function (response) {
                    if (response.success) {
                        if (selectedFields.includes('page_title')) {
                            textfields.pageTitle(
                                response.textfields.page_title
                            );
                            textfields.originalPageTitle(
                                response.textfields.page_title
                            );
                        }
                        if (selectedFields.includes('page_description')) {
                            textfields.pageDescription(
                                response.textfields.page_description
                            );
                            textfields.originalPageDescription(
                                response.textfields.page_description
                            );
                        }
                        if (selectedFields.includes('product_description')) {
                            textfields.productDescription(
                                response.textfields.product_description
                            );
                            textfields.originalProductDescription(
                                response.textfields.product_description
                            );
                        }
                        if (
                            selectedFields.includes('short_product_description')
                        ) {
                            textfields.productShortDescription(
                                response.textfields.short_product_description
                            );
                            textfields.originalProductShortDescription(
                                response.textfields.short_product_description
                            );
                        }
                        if (selectedFields.includes('open_graph')) {
                            textfields.openGraph(
                                response.textfields.open_graph
                            );
                            textfields.originalOpenGraph(
                                response.textfields.open_graph
                            );
                        }
                    } else {
                        console.log('response.message', response.message);
                        errorMessagesModel.messages.push(response.message);
                    }
                }
            });
        },

        /**
         * Reset settings.
         *
         * @param {string} type
         * @returns {void}
         */
        reset: function (type) {
            if (type === 'tones') {
                self.tonesSelected(self.defaultTones);
                self.stylesSelected(self.defaultStyle);
                self.saveTonesAndStyles();
            }

            if (type === 'audience') {
                self.audienceSelected([...self.defaultAudiences]);
            }
        },

        /**
         * Select all tones.
         */
        selectAllTones: function () {
            var tones = self.tones().map(function (tone) {
                if (!$('[name="tones[]"][value="' + tone.id + '"]').attr('disabled')
                    && !$('[name="tones[]"][value="' + tone.id + '"]').hasClass('wtai-disabled')) {
                    return tone.id;
                }
            }).filter(function (element) {
                return element != null;
            });

            this.canUpdateTones = false;
            if (this.selectAllTonesValue()) {
                self.tonesSelected(tones);
            } else {
                self.tonesSelected([]);
            }
            this.canUpdateTones = true;

            self.saveTonesAndStyles();
        },

        /**
         * Observe tones selected.
         */
        observeTonesSelected: function () {
            var tonesSelectedCount = self.tonesSelected() ? self.tonesSelected().length : 0;

            if (self.tones().length === tonesSelectedCount) {
                this.selectAllTonesValue(true);
            } else {
                this.selectAllTonesValue(false);
            }
        },

        /**
         * Select all audience.
         */
        selectAllAudience: function () {
            var allAudience = self.audience().map(function (data) {
                if (!$('[name="audience[]"][value="' + data.id + '"]').attr('disabled')) {
                    return data.id;
                }
            });

            this.canUpdateAudience = false;
            if (this.selectAllAudienceValue()) {
                self.audienceSelected(allAudience);
            } else {
                self.audienceSelected([]);
            }
            this.canUpdateAudience = true;
        },

        /**
         * Observe audience selected.
         */
        observeAudienceSelected: function () {
            var audienceSelectedCount = self.audienceSelected() ? self.audienceSelected().length : 0;

            if (
                self.audience().length === audienceSelectedCount &&
                self.audience().length > 0
            ) {
                this.selectAllAudienceValue(true);
            } else {
                this.selectAllAudienceValue(false);
            }
        },

        /**
         * Check if checkboxes are valid.
         */
        isCheckboxesValid: function () {
            var tonesSelectedCount = this.tonesSelected() ? this.tonesSelected().length : 0;

            if (tonesSelectedCount === 0) {
                this.error($t('Please select at least one tone.'));
                return false;
            } else if (
                tonesSelectedCount === 1 &&
                this.tonesSelected()[0] === 'custom' &&
                this.customTone().trim() === ''
            ) {
                this.error($t('Write your specific tone...'));
                return false;
            }

            if (this.stylesSelected() === '') {
                this.error($t('Please select a style.'));
                return false;
            } else if (
                this.stylesSelected() === 'custom' &&
                this.customStyle().trim() === ''
            ) {
                this.error($t('Write your specific style...'));
                return false;
            }

            return true;
        },

        /**
         * Check if selected fields has media or directive.
         */
        hasMediaOrDirective: function () {
            var fields = this.getSelectedFieldValues();

            if (fields.length === 0) {
                return false;
            }

            return this.directiveRegex().some(pattern => {
                pattern = new RegExp(pattern, 'si');
                return fields.some(field => {
                    let matches = field.match(pattern);

                    return matches && matches.length;
                });
            });
        },

        /**
         * Get selected field values.
         */
        getSelectedFieldValues: function () {
            var fields = [];

            if (self.selectedFields().includes('product_description')) {
                fields.push(textfields.productDescription());
            }

            if (self.selectedFields().includes('short_product_description')) {
                fields.push(textfields.productShortDescription());
            }

            return fields;
        }
    });
});
