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

define([
    'jquery',
    'uiComponent',
    'underscore',
    'WriteTextAI_WriteTextAI/js/model/edit',
    'WriteTextAI_WriteTextAI/js/model/edit/textfields',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/product',
    'WriteTextAI_WriteTextAI/js/model/edit/settings',
    'WriteTextAI_WriteTextAI/js/utils/edit/textfields',
    'WriteTextAI_WriteTextAI/js/model/edit/transfer/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/mark-reviewed',
    'WriteTextAI_WriteTextAI/js/model/total-credits',
    'WriteTextAI_WriteTextAI/js/model/edit/review-status',
    'WriteTextAI_WriteTextAI/js/model/edit/gallery',
    'WriteTextAI_WriteTextAI/js/model/edit/error-messages',
    'WriteTextAI_WriteTextAI/js/model/edit/preferences',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keywords',
    'WriteTextAI_WriteTextAI/js/model/signalr',
    'mage/translate',
    'ko',
    'wysiwygAdapter',
    'Magento_Ui/js/modal/confirm',
    'wtaiOwlCarousel',
    'accordion',
    'jquery/ui',
    'mage/adminhtml/wysiwyg/tiny_mce/setup'
], function (
    $,
    Component,
    _,
    editData,
    textfields,
    generateSettings,
    product,
    settings,
    textfieldsUtils,
    transferSettings,
    markReviewed,
    totalCredits,
    reviewStatus,
    gallery,
    errorMessagesModel,
    preferences,
    keywordAnalysisData,
    keywordsData,
    signalRModel,
    $t,
    ko,
    wysiwygAdapter,
    confirm
) {
    'use strict';

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

    /**
     * Highlight words in a textarea
     */
    ko.bindingHandlers.highlightWords = {
        update: textfieldsUtils.highlightWords
    };

    return Component.extend({
        defaults: {
            productId: '',
            storeId: '',
            isViewerUser: false,
            pageTitle: '',
            pageDescription: '',
            productDescription: '',
            productShortDescription: '',
            openGraph: '',
            descMin: 0,
            descMax: 0,
            excMin: 0,
            excMax: 0,
            selectedFields: [],
            widgetInitialized: false,
            mgPageTitle: '',
            mgPageDescription: '',
            mgProductDescription: '',
            mgProductShortDescription: '',
            mgOpenGraph: '',
            highlightPronouns: false,
            formal: false,
            language: '',
            formalLanguageSupport: [],
            formalLanguages: [],
            selectedStores: [],
            statuses: {
                pageTitleGenerateStatus: false,
                pageDescriptionGenerateStatus: false,
                productDescriptionGenerateStatus: false,
                productShortDescriptionGenerateStatus: false,
                openGraphGenerateStatus: false,
                pageTitleTransferStatus: false,
                pageDescriptionTransferStatus: false,
                productDescriptionTransferStatus: false,
                productShortDescriptionTransferStatus: false,
                openGraphTransferStatus: false
            },
            originalPageTitle: '',
            originalPageDescription: '',
            originalProductDescription: '',
            originalProductShortDescription: '',
            originalOpenGraph: '',
            reviewStatus: []
        },

        isSelectedFieldsChange: false,
        isPageTitleChange: false,
        isPageDescriptionChange: false,
        isProductDescriptionChange: false,
        isProductShortDescriptionChange: false,
        isOpenGraphChange: false,
        wysiwygInitialized: {
            productDescription: false,
            productShortDescription: false
        },
        wordsAllowed: false,
        carouselInitialized: false,
        isDescMinChange: false,
        isDescMaxChange: false,
        isExcMinChange: false,
        isExcMaxChange: false,
        isEditAllowed: false,

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

            self = this;

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

            reviewStatus.reviewStatus.subscribe(function (reviewStatus) {
                if (self.carouselInitialized) {
                    $(".wtai-review_status-tooltip .owl-carousel").trigger('destroy.owl.carousel');
                    $(".wtai-review_status-tooltip .owl-carousel").html('');
                }
                self.reviewStatus(reviewStatus);
                self.initReviewCarousel();
            });

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

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

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

            textfields.pageTitle.subscribe(function (pageTitle) {
                self.isPageTitleChange = true;
                self.pageTitle(pageTitle);
                self.isPageTitleChange = false;
            });

            textfields.pageDescription.subscribe(function (pageDescription) {
                self.isPageDescriptionChange = true;
                self.pageDescription(pageDescription);
                self.isPageDescriptionChange = false;
            });

            textfields.productDescription.subscribe(
                function (productDescription) {
                    var wysiwyg = wysiwygAdapter.get(
                        'wtaiNewProductDescription'
                    );

                    if (productDescription !== self.productDescription()) {
                        /* prevent wysiwyg cursor from resetting */
                        self.isProductDescriptionChange = true;

                        /* productDescription = textfieldsUtils.convertNewLinesToBr(productDescription); */
                        self.productDescription(productDescription);

                        if (!wysiwyg) {
                            return;
                        }

                        /* Sync scroll */
                        $(wysiwyg.getWin()).on('scroll', function (event) {
                            $('#wtaiProductDescMask').scrollTop(
                                event.currentTarget.scrollY
                            );
                            $('#wtaiProductDescMask').scrollLeft(
                                event.currentTarget.scrollX
                            );
                            if (wysiwygAdapter.get('wtaiProductDescMask') != null) {
                                wysiwygAdapter
                                    .get('wtaiProductDescMask')
                                    .contentWindow.scrollTo(
                                        event.currentTarget.scrollX,
                                        event.currentTarget.scrollY
                                    );
                            }
                        });

                        /* Set wywiwyg content */
                        wysiwyg.setContent(productDescription);

                        /* Disable wysiwyg editor */
                        if (
                            (!self.wysiwygInitialized.productDescription &&
                            $('#wtaiNewProductDescription').prop('readonly') &&
                            wysiwyg.getBody()) || !self.isEditAllowed
                        ) {
                            wysiwyg
                                .getBody()
                                .setAttribute('contenteditable', false);
                            self.wysiwygInitialized.productDescription = true;
                        }

                        self.isProductDescriptionChange = false;
                    }
                }
            );

            textfields.productShortDescription.subscribe(
                function (productShortDescription) {
                    var wysiwyg = wysiwygAdapter.get(
                        'wtaiNewShortDescription'
                    );

                    console.log(productShortDescription !== self.productShortDescription());
                    if (
                        productShortDescription !==
                        self.productShortDescription()
                    ) {
                        /* prevent wysiwyg cursor from resetting */
                        self.isProductShortDescriptionChange = true;

                        /* Set product short description */
                        /* productShortDescription = textfieldsUtils.convertNewLinesToBr(productShortDescription); */
                        self.productShortDescription(productShortDescription);

                        if (!wysiwyg) {
                            return;
                        }

                        /* Sync scroll */
                        $(wysiwyg.getWin()).on('scroll', function (event) {
                            $('#wtaiExcerptMask').scrollTop(
                                event.currentTarget.scrollY
                            );
                            $('#wtaiExcerptMask').scrollLeft(
                                event.currentTarget.scrollX
                            );
                            if (wysiwygAdapter.get('wtaiExcerptMask') != null) {
                                wysiwygAdapter
                                    .get('wtaiExcerptMask')
                                    .contentWindow.scrollTo(
                                        event.currentTarget.scrollX,
                                        event.currentTarget.scrollY
                                    );
                            }
                        });

                        /* Set wysiwyg content */
                        wysiwyg.setContent(productShortDescription);

                        /* Disable wysiwyg editor */
                        if (
                            (!self.wysiwygInitialized.productShortDescription &&
                            $('#wtaiNewShortDescription').prop('readonly') &&
                            wysiwyg.getBody()) || !self.isEditAllowed
                        ) {
                            wysiwyg
                                .getBody()
                                .setAttribute('contenteditable', false);
                            self.wysiwygInitialized.productShortDescription = true;
                        }

                        self.isProductShortDescriptionChange = false;
                    }
                }
            );

            textfields.openGraph.subscribe(function (openGraph) {
                self.isOpenGraphChange = true;
                self.openGraph(openGraph);
                self.isOpenGraphChange = false;
            });

            textfields.mgPageTitle.subscribe(function (mgPageTitle) {
                self.mgPageTitle(mgPageTitle);
            });

            textfields.mgPageDescription.subscribe(
                function (mgPageDescription) {
                    self.mgPageDescription(mgPageDescription);
                }
            );

            textfields.mgProductDescription.subscribe(
                function (mgProductDescription) {
                    var wysiwyg = wysiwygAdapter.get(
                        'wtaiProductDescription'
                    );

                    if (wysiwyg  != null) {
                        /* Set description */
                        if (mgProductDescription) {
                            wysiwyg.setContent(mgProductDescription);
                        } else {
                            wysiwyg.setContent('');
                        }
                    }

                    self.mgProductDescription(mgProductDescription);
                }
            );

            textfields.mgProductShortDescription.subscribe(
                function (mgProductShortDescription) {
                    var wysiwyg = wysiwygAdapter.get(
                        'wtaiShortDescription'
                    );
                    if (wysiwyg  != null) {
                        if (mgProductShortDescription) {
                            wysiwyg.setContent(mgProductShortDescription);
                        } else {
                            wysiwyg.setContent('');
                        }
                    }
                    
                    self.mgProductShortDescription(mgProductShortDescription);
                }
            );

            textfields.mgOpenGraph.subscribe(function (mgOpenGraph) {
                self.mgOpenGraph(mgOpenGraph);
            });

            textfields.statuses.subscribe(function (statuses) {
                self.statuses(statuses);
            });

            textfields.originalPageTitle.subscribe(function (originalPageTitle) {
                self.originalPageTitle(originalPageTitle);
            });

            textfields.originalPageDescription.subscribe(
                function (originalPageDescription) {
                    self.originalPageDescription(originalPageDescription);
                }
            );

            textfields.originalProductDescription.subscribe(
                function (originalProductDescription) {
                    self.originalProductDescription(
                        originalProductDescription
                    );
                }
            );

            textfields.originalProductShortDescription.subscribe(
                function (originalProductShortDescription) {
                    self.originalProductShortDescription(
                        originalProductShortDescription
                    );
                }
            );

            textfields.originalOpenGraph.subscribe(function (originalOpenGraph) {
                self.originalOpenGraph(originalOpenGraph);
            });

            self.pageTitle.subscribe(function (pageTitle) {
                if (!self.isPageTitleChange) {
                    textfields.pageTitle(pageTitle);
                }
            });

            self.pageDescription.subscribe(function (pageDescription) {
                if (!self.isPageDescriptionChange) {
                    textfields.pageDescription(pageDescription);
                }
            });

            self.openGraph.subscribe(function (openGraph) {
                if (!self.isOpenGraphChange) {
                    textfields.openGraph(openGraph);
                }
            });

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

            textfields.highlightPronouns.subscribe(
                function (highlightPronouns) {
                    self.highlightPronouns(highlightPronouns);
                }
            );

            textfields.formal.subscribe(function (formal) {
                self.formal(formal);
            });

            self.selectedFields.subscribe(function (selectedFields) {
                if (!self.isSelectedFieldsChange) {
                    let value = Object.keys(selectedFields)
                        .filter(key => selectedFields.hasOwnProperty(key))
                        .map(key => selectedFields[key]);

                    textfields.selectedFields(value);
                    self.savePreferences('single_editor', value, 'product', 'edit');
                }
            });

            self.descMin.subscribe(function (descMin) {
                generateSettings.descMin(descMin);
                settings.descMin(descMin);
                if (!self.isDescMinChange) {
                    self.savePreferences('desc_min', descMin);
                }
            });

            self.descMax.subscribe(function (descMax) {
                generateSettings.descMax(descMax);
                settings.descMax(descMax);
                if (!self.isDescMaxChange) {
                    self.savePreferences('desc_max', descMax);
                }
            });

            self.excMin.subscribe(function (excMin) {
                generateSettings.excMin(excMin);
                settings.excMin(excMin);
                if (!self.isExcMinChange) {
                    self.savePreferences('exc_min', excMin);
                }
            });

            self.excMax.subscribe(function (excMax) {
                generateSettings.excMax(excMax);
                settings.excMax(excMax);
                if (!self.isExcMaxChange) {
                    self.savePreferences('exc_max', excMax);
                }
            });

            editData.opened.subscribe(function (opened) {
                if (opened && !self.widgetInitialized) {
                    $('.wtai-edit-modal .wtai-input-number').spinner({
                        numberFormat: 'n',
                        min: self.rules.minOutputWords,
                        max: self.rules.maxOutputWords,
                        disabled: !self.wordsAllowed,
                        spin: function (event, ui) {
                            var value = ui.value,
                                name = $(event.target).attr('name');
                            
                            switch (name) {
                                case 'product_description_min':
                                    self.isDescMinChange = true;
                                    self.descMin(value);
                                    self.isDescMinChange = false;
                                    break;
                                case 'product_description_max':
                                    self.isDescMaxChange = true;
                                    self.descMax(value);
                                    self.isDescMaxChange = false;
                                    break;
                                case 'short_description_min':
                                    self.isExcMinChange = true;
                                    self.excMin(value);
                                    self.isExcMinChange = false;
                                    break;
                                case 'short_description_max':
                                    self.isExcMaxChange = true;
                                    self.excMax(value);
                                    self.isExcMaxChange = false;
                                    break;
                            }
                        },
                        change: function (event) {
                            var value = event.target.value,
                                name = $(event.target).attr('name');
                            
                            switch (name) {
                                case 'product_description_min':
                                    self.descMin(value);
                                    break;
                                case 'product_description_max':
                                    self.descMax(value);
                                    break;
                                case 'short_description_min':
                                    self.excMin(value);
                                    break;
                                case 'short_description_max':
                                    self.excMax(value);
                                    break;
                            }
                        }
                    });

                    self.initEditors();
                    self.initUnsavedChanges();
                }
            });

            settings.descMin.subscribe(function (descMin) {
                self.isDescMinChange = true;
                self.descMin(descMin);
                self.isDescMinChange = false;
            });

            settings.descMax.subscribe(function (descMax) {
                self.isDescMaxChange = true;
                self.descMax(descMax);
                self.isDescMaxChange = false;
            });

            settings.excMin.subscribe(function (excMin) {
                self.isExcMinChange = true;
                self.excMin(excMin);
                self.isExcMinChange = false;
            });

            settings.excMax.subscribe(function (excMax) {
                self.isExcMaxChange = true;
                self.excMax(excMax);
                self.isExcMaxChange = false;
            });

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

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

            transferSettings.selectedStores.subscribe(
                function (selectedStores) {
                    self.selectedStores([]);
                    for (let key in selectedStores) {
                        if (selectedStores.hasOwnProperty(key)) {
                            self.selectedStores.push(selectedStores[key]);
                        }
                    }
                }
            );
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super().observe([
                'productId',
                'storeId',
                'isViewerUser',
                'pageTitle',
                'pageDescription',
                'productDescription',
                'productShortDescription',
                'openGraph',
                'descMin',
                'descMax',
                'excMin',
                'excMax',
                'selectedFields',
                'mgPageTitle',
                'mgPageDescription',
                'mgProductDescription',
                'mgProductShortDescription',
                'mgOpenGraph',
                'highlightPronouns',
                'formal',
                'language',
                'formalLanguageSupport',
                'formalLanguages',
                'selectedStores',
                'statuses',
                'originalPageTitle',
                'originalPageDescription',
                'originalProductDescription',
                'originalProductShortDescription',
                'originalOpenGraph',
                'reviewStatus'
            ]);

            this.keywordsUsed = ko.computed(function () {
                return textfields.keywordsUsed();
            }, this);

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

                return keywordAnalysisOngoing && isProductOptimizing;
            }, this);

            this.isKoRefreshing = ko.pureComputed(function () {
                return Boolean(
                    keywordAnalysisData.refreshingData && keywordAnalysisData.refreshingData()
                );
            });

            this.getFieldReviewStatus = function (textType) {
                var self = this;
                var result = ko.computed(function () {
                    let statuses = [];

                    if (self.reviewStatus()) {
                        self.reviewStatus().forEach(function (store) {
                            if (!store.reviews) {
                                return;
                            }
                            store.reviews.forEach(function (status) {
                                if (!status.fields) {
                                    return;
                                }
    
                                let fieldReview = status.fields.filter(function (field) {
                                    return field.field === textType && field.status >= 1;
                                });
    
                                if (fieldReview.length <= 0) {
                                    return;
                                }
    
                                statuses.push(fieldReview.shift().status);
                            });
                        });
                    }

                    let uniqueStatuses = [...new Set(statuses)];
                    switch (uniqueStatuses.length) {
                        case 1: return uniqueStatuses[0];
                        case 0: return 0;
                        default: return 3;
                    }
                });
                    
                return result();
            }.bind(this);
            
            this.isAllStoreView = ko.computed(function () {
                return Number(this.storeId()) === Number(this.defaultStoreId);
            }, this);

            this.useDefault = ko.computed(function () {
                return textfields.useDefault();
            }, this);

            this.informal = ko.computed(function () {
                return preferences.stylesSelected() === 'Internet-speak';
            });

            this.keywords = ko.computed(function () {
                return [];
            });

            this.highlighted = ko.computed(function () {
                return true;
            });

            this.optimizationData = ko.computed(function () {
                return keywordAnalysisData.optimizationData();
            });

            this.selectedKeywords = ko.computed(function () {
                return keywordsData.selectedKeywords();
            });

            return this;
        },

        /**
         * Show store review
         *
         * @param {Object} store
         * @param {String} textType
         *
         * @returns {Boolean}
         */
        showStoreReview: function (store, textType) {
            if (store.reviews.length <= 0) {
                return false;
            }

            for (let i = 0; i < store.reviews.length; i++) {
                if (self.getStatusStatus(store.reviews[i].fields, textType) >= 1) {
                    return true;
                }
            }
        },

        /**
         * Initialize review carousel
         */
        initReviewCarousel: function () {
            $(".wtai-review_status-tooltip .owl-carousel").owlCarousel({
                nav : true,
                dots: false,
                loop: true,
                items : 1,
                mouseDrag: false,
                touchDrag: false,
                pullDrag: false,
                onInitialized: self.carouselCounter,
                onChanged: self.carouselCounter
            });

            self.carouselInitialized = true;
        },

        /**
         * Carousel counter
         *
         * @param {Object} event
         * @returns {void}
         */
        carouselCounter: function (event) {
            var slides = event.relatedTarget;

            if (!event.namespace) {
                return;
            }

            $('.wtai-review_status-tooltip .owl-carousel-counter').text(
                slides.relative(slides.current()) + 1
                + ' ' + $t('of') + ' '
                + slides.items().length
            );
        },

        /**
         * Get status' status
         *
         * @param {Array} fields
         * @param {String} textType
         *
         * @returns {Number}
         */
        getStatusStatus: function (fields, textType) {
            let fieldReview = fields.filter(function (field) {
                return field.field === textType;
            });

            if (fieldReview.length <= 0) {
                return;
            }

            return fieldReview.shift().status;
        },

        /**
         * Update review status
         *
         * @param {String} textType
         * @returns {void}
         */
        updateReviewStatus: function (textType) {
            errorMessagesModel.messages([]);
            $.ajax({
                url: self.reviewUrl,
                type: 'POST',
                data: {
                    text_type: textType,
                    product_id: self.productId(),
                    store_id: self.storeId()
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                success: function (response) {
                    if (!response.success) {
                        errorMessagesModel.messages.push(response.message);
                    } else {
                        reviewStatus.reviewStatus(response.updatedReview);
                    }
                }
            });
        },

        /**
         * 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);
                    }
                }
            });
        },

        /**
         * Check if text is edited.
         *
         * @param {String} original
         * @param {String} edited
         *
         * @returns {Boolean}
         */
        isEdited: function (original, edited) {
            var originalText = original;

            originalText = textfieldsUtils.convertNewLinesToBr(originalText);

            return originalText !== edited;
        },

        /**
         * Get char count.
         *
         * @param {String} html
         * @param {Number} limit
         *
         * @returns {Number}
         */
        getCharCount: function (html, limit = null, unit = true) {
            return textfieldsUtils.getCharCount(html, limit, unit);
        },

        /**
         * Get word count.
         *
         * @param {String} html
         * @returns {Number}
         */
        getWordCount: function (html, unit = true) {
            return textfieldsUtils.getWordCount(html, unit);
        },

        /**
         * Check if text is over limit.
         *
         * @param {String} html
         * @param {Number} limit
         *
         * @returns {Boolean}
         */
        isOverLimit: function (html, limit) {
             return textfieldsUtils.isOverLimit(html, limit);
        },

        /**
         * Transfer text to Magento.
         *
         * @param {String} field
         * @param {String} value
         *
         * @returns {void}
         */
        transfer: function (field, value) {
            confirm({
                title: $.mage.__('Transfer selected to Magento'),
                content: self.confirmContent,
                modalClass: 'wtai-modal wtai-bulk-transfer-popup wtai-transfer wtai-edit',
                actions: {
                    confirm: function () {
                        self._transfer(field, value);
                    }
                },
                buttons: [{
                    text: $t('Cancel'),
                    class: 'action-secondary action-dismiss',
                    click: function (event) {
                        this.closeModal(event);
                    }
                }, {
                    text: $t('OK'),
                    class: 'action-primary action-accept',
                    click: function (event) {
                        if (
                            $('#wtaiEditTransferForm').data('validator') &&
                            $('#wtaiEditTransferForm').validation() &&
                            $('#wtaiEditTransferForm').validation('isValid')
                        ) {
                            this.closeModal(event, true);
                        }
                    }
                }]
            });
        },

        /**
         * Transfer field generated to live
         *
         * @param {String} field
         * @param {String} value
         *
         * @returns {void}
         */
        _transfer: function (field, value) {
            var url = self.transferUrl;

            errorMessagesModel.messages([]);

            signalRModel.editTitleStatusText($t('Transferring text...'));

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    product_id: self.productId(),
                    store_id: self.storeId(),
                    field: field,
                    value: value,
                    selected_stores: self.selectedStores()
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showPageTitleLoader: field === 'page_title',
                showPageDescriptionLoader: field === 'page_description',
                showProductDescriptionLoader: field === 'product_description',
                showShortDescriptionLoader: field === 'short_product_description',
                showOpenGraphLoader: field === 'open_graph',
                success: function (response) {
                    var fields = response.fields,
                        writeTextFields = {};
                        
                    writeTextFields[field] = value;

                    if (response.success) {
                        if (response.use_default) {
                            textfields.useDefault({
                                pageTitle: field === 'page_title' ?
                                    response.use_default.page_title : textfields.useDefault().pageTitle,
                                pageDescription: field === 'page_description' ?
                                    response.use_default.page_description : textfields.useDefault().pageDescription,
                                productDescription: field === 'product_description' ?
                                    response.use_default.product_description : textfields.useDefault().productDescription,
                                productShortDescription: field === 'short_product_description' ?
                                    response.use_default.short_product_description : textfields.useDefault().productShortDescription,
                                openGraph: field === 'open_graph' ?
                                    response.use_default.open_graph : textfields.useDefault().openGraph
                            });
                        }
                        markReviewed.reviewed(response.reviewed);
                        
                        if (self.selectedStores().map(String).includes(String(self.storeId()))) {
                            textfieldsUtils.updateCurrentFields(fields, [field], writeTextFields);

                            if (field === 'product_description') {
                                product.descriptionDirectiveExists(
                                    response.directives.product_description
                                );
                            }
                            
                            if (field === 'short_product_description') {
                                product.shortDescriptionDirectiveExists(
                                    response.directives.short_product_description
                                );
                            }
                        }
                        
                        reviewStatus.reviewStatus(response.updatedReview);
                    } else {
                        errorMessagesModel.messages.push(response.message);
                    }
                    signalRModel.editTitleStatusText('');
                },
                error: function () {
                    signalRModel.editTitleStatusText('');
                }
            });
        },

        /**
         * Check if field is not editable.
         *
         * @param {Boolean} status
         * @returns {Boolean}
         */
        isNotEditable: function (status) {
            if (self.keywordAnalysisOngoing()) {
                return true;
            }

            return status;
        },

        /**
         * Init unsaved changes validator
         */
        initUnsavedChanges: function () {
            $(window).on('beforeunload', function () {
                var unsavedTexts = textfields.originalPageTitle() !==
                            textfields.pageTitle() ||
                        textfields.originalPageDescription() !==
                            textfields.pageDescription() ||
                        textfields.originalProductDescription() !==
                            textfields.productDescription() ||
                        textfields.originalProductShortDescription() !==
                            textfields.productShortDescription() ||
                        textfields.originalOpenGraph() !==
                            textfields.openGraph(),
                    unsavedImage =  gallery.images().some(image => {
                        return image.original_writetext_alt !== image.writetext_alt;
                    });

                if (unsavedTexts || unsavedImage) {
                    return $t('You have unsaved changes. Are you sure you want to leave this page?');
                }
            });
        },

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

        /**
         * Sync scroll
         *
         * @param {Object} data
         * @param {Object} event
         * @param {String} elementId
         *
         * @returns {void}
         */
        syncScroll: function (data, event, elementId) {
            var elementSelector = '#' + elementId,
                scrollAmount = event.target.scrollTop,
                scrollXAmount = event.target.scrollLeft;

            $(elementSelector).scrollTop(scrollAmount);
            $(elementSelector).scrollLeft(scrollXAmount);
        },

        /**
         * Validate min and max fields.
         *
         * @param {Object} data
         * @param {Object} event
         *
         * @returns {void}
         */
        validateMinMax: function (data, event) {
            var target = event.target,
                value = Number(target.value),
                min = Number(target.min),
                max = Number(target.max),
                name = target.name;

            const mapping = {
                product_description_min: self.descMin,
                product_description_max: self.descMax,
                short_description_min: self.excMin,
                short_description_max: self.excMax
            };

            if (value < min || value > max) {
                const func = mapping[name],
                    val = value < min ? min : max;

                $(target).val(val);
                func(val);
            }
        },

        /**
         * Initialize wysiwyg editors.
         */
        initEditors: function () {
            var config = self.wysiwygConfig,
                disabledConfig = self.disabledWysiwygConfig,
                wtaIds = ['wtaiNewProductDescription', 'wtaiNewShortDescription'],
                mgIds = ['wtaiProductDescription', 'wtaiShortDescription'],
                maskIds = ['wtaiProductDescMask', 'wtaiExcerptMask'];

            wtaIds.forEach(function (id) {
                try {
                    /* eslint-disable-next-line no-undef */
                    var editor = new wysiwygSetup(id, config);

                    editor.setup('exact');
                    $(id).addClass('wtai-wysiwyg-editor').data('wysiwygEditor', editor);
                } catch (e) {
                    console.log('wysiwyg failed', e);
                }
            });


            maskIds.forEach(function (id) {
                try {
                    /* eslint-disable-next-line no-undef */
                    var editor = new wysiwygSetup(id, config);

                    editor.setup('exact');
                    $(id)
                        .addClass('wtai-wysiwyg-editor wtai-wysiwyg-mask')
                        .data('wysiwygEditor', editor);
                } catch (e) {
                    console.log('wysiwyg failed', e);
                }
            });

            mgIds.forEach(function (id) {
                try {
                    /* eslint-disable-next-line no-undef */
                    var editor = new wysiwygSetup(id, disabledConfig);

                    editor.setup('exact');
                    $(id).addClass('wtai-wysiwyg-editor').data('wysiwygEditor', editor);
                } catch (e) {
                    console.log('wysiwyg failed', e);
                }
            });

            if (wysiwygAdapter.get('wtaiNewProductDescription') != null) {
                wysiwygAdapter.get('wtaiNewProductDescription').on("change", function () {
                    if (!self.isProductDescriptionChange) {
                        textfields.productDescription(self.productDescription());
                    }
                });
            }
            if (wysiwygAdapter.get('wtaiNewShortDescription') != null) {
                wysiwygAdapter.get('wtaiNewShortDescription').on("change", function () {
                    if (!self.isProductShortDescriptionChange) {
                        textfields.productShortDescription(self.productShortDescription());
                    }
                });
            }
        },

        /**
         * Convert pronouns to string.
         *
         * @param {Array} pronouns
         *
         * @returns {String}
         */
        convertPronounsToString: function (pronouns) {
            if (pronouns.length <= 0) {
                return '';
            }

            return pronouns.join(', ');
        }
    });
});
