// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

Ext.define('Shopware.apps.ViisonCommonMigration.controller.Main', {
    extend: 'Ext.app.Controller',

    mixins: [
        'Shopware.apps.ViisonCommonApp.Mixin',
    ],
    viisonSnippetNamespace: 'backend/viison_common_migration/main',

    /**
     * @Override
     */
    init: function () {
        this.callParent(arguments);

        this.control({
            'viison_common_migration-error_window': {
                clickDisablePluginsButton: this.onClickDisablePluginsButton,
                clickReloadBackendButton: this.onClickReloadBackendButton,
                retry: this.onRetry,
            },
        });

        this.executeMigrations();
    },

    /**
     * Sends a request to the server to execute all executable migrations
     */
    executeMigrations: function () {
        var fiveMinutesInMilliseconds = 5 * 60 * 1000;
        var tenSecondsInMilliseconds = 10 * 1000;
        // The max execution time of the migration framework is 5 minutes. Therefore allow 5 minutes plus 10 seconds
        // (to handle the request/response boilerplate) for the request.
        var timeoutInMilliseconds = fiveMinutesInMilliseconds + tenSecondsInMilliseconds;
        Ext.Ajax.request({
            url: ViisonCommonApp.assembleBackendUrl('ViisonCommonMigration/executeMigrations'),
            scope: this,
            timeout: timeoutInMilliseconds,
            success: function (response) {
                var responseData = Ext.JSON.decode(response.responseText, true);
                if (!responseData || !responseData.success) {
                    this.showErrorDialogForFailedRequest(response);
                }
                var migrationExecutionResultStore = Ext.create('Shopware.apps.ViisonCommonMigration.store.MigrationExecutionResult');
                migrationExecutionResultStore.loadData([responseData.data]);
                var migrationExecutionResult = migrationExecutionResultStore.first();

                this.clearCaches(migrationExecutionResult.getInvalidatedCaches());

                if (migrationExecutionResult.hasExecutableMigrations()) {
                    // If the migration store has executable migrations AFTER the execution, it means there went s.th.
                    // wrong
                    this.showErrorWindow(migrationExecutionResult);

                    return;
                }

                if (migrationExecutionResult.getMessages().length === 0) {
                    // The sub app should be absolutely quiet if no migrations has a message to be shown to the user
                    return;
                }

                Shopware.Notification.createStickyGrowlMessage({
                    title: this.getViisonSnippet('growlMessage/successfulMigration/title'),
                    text: this.getViisonSnippet('growlMessage/successfulMigration/text'),
                    btnDetail: {
                        callback: function () {
                            this.showSuccessWindow(migrationExecutionResult);
                        },
                        scope: this,
                    },
                });
            },
            failure: function (response) {
                this.showErrorDialogForFailedRequest(response);
            },
        });
    },

    /**
     * Sends a requests to the server to clear Shopware caches.
     *
     * @param {string[]} caches The names of the caches to clear
     */
    clearCaches: function (caches) {
        if (caches.length === 0) {
            return;
        }
        var requestParams = {};
        caches.forEach(function (cache) {
            requestParams[cache] = 'on';
        });

        Ext.Ajax.request({
            url: ViisonCommonApp.assembleBackendUrl('Cache/clearCache'),
            method: 'post',
            params: caches,
            success: function (response) {
                var responseData = Ext.JSON.decode(response.responseText);

                if (!responseData.success) {
                    this.showErrorDialogForFailedRequest(response);
                }

                if (caches.indexOf('theme') >= 0 || caches.indexOf('frontend') >= 0) {
                    Shopware.app.Application.fireEvent('shopware-theme-cache-warm-up-request');
                }
            },
            failure: function (response) {
                this.showErrorDialogForFailedRequest(response);
            },
            scope: this,
        });
    },

    /**
     * Shows the error window for a MigrationExecutionResult
     *
     * @param {Shopware.apps.ViisonCommonMigration.model.MigrationExecutionResult} migrationExecutionResult
     */
    showErrorWindow: function (migrationExecutionResult) {
        Ext.create('Shopware.apps.ViisonCommonMigration.view.error.Window', {
            migrationExecutionResult: migrationExecutionResult,
            subApp: this.subApplication,
        });
    },

    /**
     * Shows the success window for a MigrationExecutionResult
     *
     * @param {Shopware.apps.ViisonCommonMigration.model.MigrationExecutionResult} migrationExecutionResult
     */
    showSuccessWindow: function (migrationExecutionResult) {
        Ext.create('Shopware.apps.ViisonCommonMigration.view.success.Window', {
            migrationExecutionResult: migrationExecutionResult,
        });
    },

    /**
     * Handles event when the user clicks the 'disable plugins' button
     *
     * @param {Shopware.apps.ViisonCommonMigration.view.error.Window} migrationWindow
     */
    onClickDisablePluginsButton: function (migrationWindow) {
        this.getViisonSnippet('loadMask/disablingPlugins');
        Ext.Ajax.request({
            url: ViisonCommonApp.assembleBackendUrl('ViisonCommonMigration/disablePluginsWithExecutableMigrations'),
            success: function (response) {
                var responseData = Ext.JSON.decode(response.responseText, true);

                if (!responseData.success) {
                    this.showError(responseData.message);
                }

                this.clearCaches(responseData.data.invalidatedCaches);
                migrationWindow.migrationLog.appendPluginDisablingResultData(responseData.data);
                migrationWindow.reloadBackendButton.show();
                migrationWindow.disablePluginsButton.hide();
                migrationWindow.retryButton.hide();
            },
            failure: function (response) {
                this.showError(response.statusText);
            },
            callback: function () {
                migrationWindow.setLoading(false);
            },
            scope: this,
        });
    },

    /**
     * Handles event when the user clicks the 'reload backend' button
     *
     * @param {Shopware.apps.ViisonCommonMigration.view.error.Window} migrationWindow
     */
    onClickReloadBackendButton: function (migrationWindow) {
        this.reloadBackend(migrationWindow);
    },

    /**
     * Handles event when the user clicks the 'retry' button
     *
     * @param {Shopware.apps.ViisonCommonMigration.view.error.Window} migrationWindow
     */
    onRetry: function (migrationWindow) {
        // When the backend is reloaded, all failed migrations will be retried
        this.reloadBackend(migrationWindow);
    },

    /**
     * Reloads the backend and shows a loading mask about that in the given window.
     *
     * @param {Ext.window.Window} window
     */
    reloadBackend: function (window) {
        window.setLoading(this.getViisonSnippet('loadMask/reloadingBackend'));
        // eslint-disable-next-line no-restricted-globals
        location.reload();
    },

    /**
     * @param {XMLHttpRequest} XMLHttpRequest
     */
    showErrorDialogForFailedRequest: function (XMLHttpRequest) {
        var errorMessage = this.getErrorMessageFromXMLHttpRequest(XMLHttpRequest);
        var dialogMessage = this.getViisonSnippet('dialog/error/body') + '\n\n' + errorMessage;

        Ext.Msg.show({
            title: this.getViisonSnippet('dialog/error/title'),
            msg: dialogMessage,
            buttons: Ext.Msg.OK,
            icon: Ext.Msg.ERROR,
        });
    },

    /**
     * @param {XMLHttpRequest} XMLHttpRequest
     */
    getErrorMessageFromXMLHttpRequest: function (XMLHttpRequest) {
        var json = Ext.JSON.decode(XMLHttpRequest.responseText, true);

        if (json) {
            if (json.success) {
                return '';
            }

            return json.message;
        }

        return XMLHttpRequest.statusText + '\n\n' + XMLHttpRequest.responseText;
    },
});
