/*
 *  Copyright 2023 Anyware Services
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 * This tool displays all migrations statuses
 */
Ext.define('Ametys.plugins.admin.migration.MigrationsAction', {
    singleton: true,

    /** 
     * @private
     * Get today filename of the migration log
     * @return {String} The today migration log filename
     */
    _getFilename: function()
    {
        return "migration-" + Ext.Date.format(new Date(), "Y-m-d") + ".log";
    },

    /**
     * Open the migration log of the day
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */    
    openLog: function(controller)
    {
        Ametys.tool.ToolsManager.openTool("uitool-archived-logs", {id: Ametys.plugins.admin.migration.MigrationsAction._getFilename(), title: Ametys.plugins.admin.migration.MigrationsAction._getFilename(), path: Ametys.plugins.admin.migration.MigrationsAction._getFilename()});
    },

    /**
     * Open the direct logs about migrations 
     */    
    directLog: function(controller)
    {
        Ametys.tool.ToolsManager.openTool('uitool-server-logs', {id: controller.getInitialConfig('category'), category: controller.getInitialConfig('category'), title: controller.getInitialConfig('logtool-label')}, "cr");
    },

    /**
     * Download the migration log of the day
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */    
    downloadLog: function(controller)
    {
        Ametys.plugins.admin.logs.LogsActions.downloadFiles([Ametys.plugins.admin.migration.MigrationsAction._getFilename()]);
    },
   
    /**
     * Acknowledge the selected version
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    acknowledge: function(controller)
    {
        Ext.create('Ext.window.MessageBox', {
            minPromptWidth: 500
        }).prompt("{{i18n PLUGINS_ADMIN_MIGRATIONS_ACKNOWLEDGE_CONFIRM_TITLE}}", 
                    "{{i18n PLUGINS_ADMIN_MIGRATIONS_ACKNOWLEDGE_CONFIRM_TEXT}}", 
                    Ext.bind(this._acknowledge, this, [controller], 1),
                    this,
                    false,
                    "Manually marked as done. " + controller.getMatchingTargets()[0].getParameters()['comment']
        );
    },
    
    /**
     * @private
     * Callback to actually acknowledge the version
     * @param {String} answer Will do the acknowledge if 'yes'
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller of the clicked button
     */
    _acknowledge: function(answer, controller, value)
    {
        if (answer == 'ok')
        {
            var targets = controller.getMatchingTargets();
            for (var i = 0; i < targets.length; i++)
            {
                var args = [
                    targets[i].getParameters()['componentId'], 
                    targets[i].getParameters()['internal'],
                    targets[i].getParameters()['versionListId'], 
                    targets[i].getParameters()['version']
                ];
                controller.serverCall(
                    'acknowledge', 
                    [...args, value], 
                    Ext.bind(this._acknowledgeCb, this),
                    { 
                        errorMessage: true,
                        refreshing: true,
                        arguments: [...args, targets[i].getParameters()['type'], targets[i].getParameters()['comment']]
                    }
                ); 
            }
        }
    },
    
    /**
     * @private
     * Callback after server action
     * @param {Object} value The server returned value: void here
     * @param {Object} args The serverCall arguments
     */
    _acknowledgeCb: function(value, args)
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.MODIFIED,
            targets: {
                id: Ametys.message.MessageTarget.MIGRATION,
                parameters: {                        
                    componentId: args[0], 
                    internal: args[1],
                    versionListId: args[2],
                    version: args[3],
                    type: args[4],
                    comment: args[5]
                }
            }
        });
    },   
   
    /**
     * Remove the selected version
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    delete: function(controller)
    {
        Ametys.Msg.confirm ("{{i18n PLUGINS_ADMIN_MIGRATIONS_DELETE_CONFIRM_TITLE}}", 
                    "{{i18n PLUGINS_ADMIN_MIGRATIONS_DELETE_CONFIRM_TEXT}}", 
                    Ext.bind(this._delete, this, [controller], 1));
    },
    
    /**
     * @private
     * Callback to actually delete the version
     * @param {String} answer Will do the deletion if 'yes'
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller of the clicked button
     */
    _delete: function(answer, controller)
    {
        if (answer == 'yes')
        {
            var targets = controller.getMatchingTargets();
            for (var i = 0; i < targets.length; i++)
            {
                var args = [
                    targets[i].getParameters()['componentId'], 
                    targets[i].getParameters()['internal'],
                    targets[i].getParameters()['versionListId'], 
                    targets[i].getParameters()['version']
                ];
                controller.serverCall(
                    'deleteVersion', 
                    args, 
                    Ext.bind(this._deleteCb, this),
                    { 
                        errorMessage: true,
                        refreshing: true,
                        arguments: [...args, targets[i].getParameters()['type'], targets[i].getParameters()['comment']]
                    }
                ); 
            }
        }
    },
    
    /**
     * @private
     * Callback after server action
     * @param {Object} value The server returned value: void here
     * @param {Object} args The serverCall arguments
     */
    _deleteCb: function(value, args)
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.DELETED,
            targets: {
                id: Ametys.message.MessageTarget.MIGRATION,
                parameters: {                        
                    componentId: args[0], 
                    internal: args[1],
                    versionListId: args[2],
                    version: args[3],
                    type: args[4],
                    comment: args[5]
                }
            }
        });
    },
    
    /**
     * Create a new unexisting version
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    create: function(controller)
    {
        this._box = Ext.create('Ametys.window.DialogBox', {
            title: "{{i18n PLUGINS_ADMIN_MIGRATIONS_CREATE_DIALOG_LABEL}}",
            iconCls: "ametysicon-code-misc-binary decorator-ametysicon-sign-raw-add",
            
            layout: 'anchor',
            width: 700,
            items: [
                {
                    xtype: 'component',
                    html: "{{i18n PLUGINS_ADMIN_MIGRATIONS_CREATE_DIALOG_TEXT}}",
                    anchor: '100%'
                }, {
                    xtype: 'textfield',
                    itemId: 'version',
                    labelAlign: 'top',
                    labelSeparator: '',
                    fieldLabel: "{{i18n PLUGINS_ADMIN_MIGRATIONS_CREATE_DIALOG_VERSION_LABEL}}*",
                    allowBlank: false,
                    regex: /^[a-z0-9-_]{1,24}$/i,
                    regexText: "{{i18n PLUGINS_ADMIN_MIGRATIONS_CREATE_DIALOG_VERSION_REGEX}}",
                    width: 200
                }, {
                    xtype: 'textfield',
                    itemId: 'comment',
                    labelAlign: 'top',
                    labelSeparator: '',
                    fieldLabel: "{{i18n PLUGINS_ADMIN_MIGRATIONS_CREATE_DIALOG_COMMENT_LABEL}}",
                    anchor: '100%',
                    value: "Manually created version"
                }  
            ],
            
            closeAction: 'destroy',
             defaultFocus: 'version',
            
            referenceHolder: true,
            defaultButton: 'okButton',
            
            buttons : [{
                reference: 'okButton',
                text: "{{i18n PLUGINS_ADMIN_MIGRATIONS_CREATE_DIALOG_OK}}",
                handler: Ext.bind(this._createCb, this, [controller])
            }, {
                text: "{{i18n PLUGINS_ADMIN_MIGRATIONS_CREATE_DIALOG_CANCEL}}",
                handler: Ext.bind(function() {this._box.hide();}, this)
            }]
        });
        this._box.show();
    },
    
    /**
     * @private
     * When validating the creation
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    _createCb: function(controller)
    {
        if (!this._box.getComponent('version').isValid())
        {
            return;
        }
        
        var targets = controller.getMatchingTargets();
        for (var i = 0; i < targets.length; i++)
        {
            var args = [
                targets[i].getParameters()['componentId'], 
                targets[i].getParameters()['internal'],
                targets[i].getParameters()['versionListId']
            ];
            controller.serverCall(
                'acknowledge', 
                [...args, this._box.getComponent('version').getValue(), this._box.getComponent('comment').getValue()], 
                Ext.bind(this._createCb2, this),
                { 
                    errorMessage: true,
                    refreshing: true,
                    arguments: [...args, targets[i].getParameters()['type']]
                }
            );
        }
    },
    
    /**
     * @private
     * Callback after server action
     * @param {Object} value The server returned value: void here
     * @param {Object} args The serverCall arguments
     */
    _createCb2: function(value, args)
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.MODIFIED,
            targets: {
                id: Ametys.message.MessageTarget.MIGRATION_NODE,
                parameters: {                        
                    componentId: args[0], 
                    internal: args[1],
                    versionListId: args[2],
                    type: args[3],
                }
            }
        });
        
        this._box.close();
    },
    
    /**
     * Remove the selected list of version
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    deleteList: function(controller)
    {
        Ametys.Msg.confirm ("{{i18n PLUGINS_ADMIN_MIGRATIONS_DELETELIST_CONFIRM_TITLE}}", 
                    "{{i18n PLUGINS_ADMIN_MIGRATIONS_DELETELIST_CONFIRM_TEXT}}", 
                    Ext.bind(this._deleteList, this, [controller], 1));
    },
    
    /**
     * @private
     * Callback to actually delete the list of versions
     * @param {String} answer Will do the deletion if 'yes'
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller of the clicked button
     */
    _deleteList: function(answer, controller)
    {
        if (answer == 'yes')
        {
            var targets = controller.getMatchingTargets();
            for (var i = 0; i < targets.length; i++)
            {
                var args = [
                    targets[i].getParameters()['componentId'], 
                    targets[i].getParameters()['internal'],
                    targets[i].getParameters()['versionListId']
                ];
                controller.serverCall(
                    'deleteAllVersions', 
                    args, 
                    Ext.bind(this._deleteListCb, this),
                    { 
                        errorMessage: true,
                        refreshing: true,
                        arguments: [...args, targets[i].getParameters()['type']]
                    }
                ); 
            }
        }
    },
    
    /**
     * @private
     * Callback after server action
     * @param {Object} value The server returned value: void here
     * @param {Object} args The serverCall arguments
     */
    _deleteListCb: function(value, args)
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.DELETED,
            targets: {
                id: Ametys.message.MessageTarget.MIGRATION_NODE,
                parameters: {                        
                    componentId: args[0], 
                    internal: args[1],
                    versionListId: args[2],
                    type: args[3],
                }
            }
        });
    },
    
    /**
     * Execute the selected version
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    execute: function(controller)
    {
        Ametys.Msg.confirm ("{{i18n PLUGINS_ADMIN_MIGRATIONS_EXECUTE_CONFIRM_TITLE}}", 
                    "{{i18n PLUGINS_ADMIN_MIGRATIONS_EXECUTE_CONFIRM_TEXT}}", 
                    Ext.bind(this._execute, this, [controller], 1));
    },
        
    _execute: function(answer, controller)
    {
        if (answer == 'yes')
        {
            var targets = controller.getMatchingTargets();
            for (var i = 0; i < targets.length; i++)
            {
                var args = [
                    targets[i].getParameters()['componentId'], 
                    targets[i].getParameters()['internal'],
                    targets[i].getParameters()['versionListId'], 
                    targets[i].getParameters()['version']
                ];
                controller.serverCall(
                    'doAction', 
                    [...args, false, null], 
                    Ext.bind(this._executeCb, this),
                    { 
                        errorMessage: true,
                        refreshing: true,
                        arguments: [...args, targets[i].getParameters()['type'], targets[i].getParameters()['comment']]
                    }
                ); 
            }
        }
    },
    
    /**
     * @private
     * Callback after server action
     * @param {Object} restart The server returned value: true if a the actions requires a restart
     * @param {Object} args The serverCall arguments
     */
    _executeCb: function(restart, args)
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.MODIFIED,
            targets: {
                id: Ametys.message.MessageTarget.MIGRATION,
                parameters: {                        
                    componentId: args[0], 
                    internal: args[1],
                    versionListId: args[2],
                    version: args[3],
                    type: args[4],
                    comment: args[5]
                }
            }
        });
        if (restart)
        {
            this._displayRestartMessage();
        }
    },
    
    /**
     * Acknowledge the selected version
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    executeAndAcknowledge: function(controller)
    {
        let comment = controller.getMatchingTargets()[0].getParameters()['comment'];
        if (comment.startsWith("Automatic Upgrade"))
        {
            comment = "Manual Upgrade" + comment.slice(17);
        }
        else if (!comment.startsWith("Manual Upgrade"))
        {
            comment = "Manual Upgrade" + (comment ? ": " + comment : "");
        }
        Ext.create('Ext.window.MessageBox', {
            minPromptWidth: 500
        }).prompt("{{i18n PLUGINS_ADMIN_MIGRATIONS_EXECUTE_AND_ACKNOWLEDGE_CONFIRM_TITLE}}", 
                    "{{i18n PLUGINS_ADMIN_MIGRATIONS_EXECUTE_AND_ACKNOWLEDGE_CONFIRM_TEXT}}", 
                    Ext.bind(this._executeAndAcknowledge, this, [controller], 1),
                    this,
                    false,
                    comment
        );
    },
    
    /**
     * @private
     * Callback to actually acknowledge the version
     * @param {String} answer Will do the acknowledge if 'yes'
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller of the clicked button
     */
    _executeAndAcknowledge: function(answer, controller, value)
    {
        if (answer == 'ok')
        {
            var targets = controller.getMatchingTargets();
            for (var i = 0; i < targets.length; i++)
            {
                var args = [
                    targets[i].getParameters()['componentId'], 
                    targets[i].getParameters()['internal'],
                    targets[i].getParameters()['versionListId'], 
                    targets[i].getParameters()['version']
                ];
                controller.serverCall(
                    'doAction', 
                    [...args, true, value], 
                    Ext.bind(this._executeAndAcknowledgeCb, this),
                    { 
                        errorMessage: true,
                        refreshing: true,
                        arguments: [...args, targets[i].getParameters()['type'], targets[i].getParameters()['comment']]
                    }
                ); 
            }
        }
    },
    
    /**
     * @private
     * Callback after server action
     * @param {Object} restart The server returned value: true if a the actions requires a restart
     * @param {Object} args The serverCall arguments
     */
    _executeAndAcknowledgeCb: function(restart, args)
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.MODIFIED,
            targets: {
                id: Ametys.message.MessageTarget.MIGRATION,
                parameters: {                        
                    componentId: args[0], 
                    internal: args[1],
                    versionListId: args[2],
                    version: args[3],
                    type: args[4],
                    comment: args[5]
                }
            }
        });
        if (restart)
        {
            this._displayRestartMessage();
        }
    },
    
    _displayRestartMessage: function()
    {
        Ametys.Msg.alert ("{{i18n PLUGINS_ADMIN_MIGRATIONS_RESTART_REQUIRED_TITLE}}", 
            "{{i18n PLUGINS_ADMIN_MIGRATIONS_RESTART_REQUIRED_TEXT}}");
            
    }
});