/*
 *  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.
 */
 
 /**
  * Actions on workflow step and actions's common components
  */
 Ext.define('Ametys.plugins.workflow.actions.WorkflowEditionAction', {
    singleton: true,
    
    /**
    * @private
    * @property {String} _mode 'new' or 'edit' 
    */
    
    /**
    * @private
    * @property {String} _workflowName id of the workflow
    */
    
    /**
    * @private
    * @property {String} _stepId id of current step parent
    */
    
    /**
    * @private
    * @property {String} _actionId id of current action parent
    */
    
    /**
    * @private
    * @property {String} _oldName name of the property before edition
    */
    
    /**
    * @private
    * @property {String[]} _unavailableNames properties names already present in parent
    */
   
    /**
    * @private
    * @property {Ametys.window.DialogBox} _propertyBox the creation / edition dialog box for properties
    */
    
     /**
     * Add a new property
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    addProperty: function(controller)
    {
        var target = Ametys.message.MessageTargetHelper.findTarget(controller.getMatchingTargets());
        var stepTarget = target ? target.getSubtarget(function(target){return target.getId() == Ametys.message.MessageTarget.WORKFLOW_STEP}) : null;
        if (!stepTarget)
        {
            return; 
        }
        var actionTarget = target.getSubtarget(function(target){return target.getId() == Ametys.message.MessageTarget.WORKFLOW_ACTION});
        this._workflowName = target.getParameters().id;
        this._stepId = stepTarget.getParameters().id;
        this._actionId = actionTarget != null ? actionTarget.getParameters().id : null;
        
        this._mode = "new";
        
        Ametys.plugins.workflow.dao.WorkflowPropertyDAO.getPropertiesNames([this._workflowName, parseInt(this._stepId), parseInt(this._actionId)], Ext.bind(this._getPropertiesNamesCB, this)); 
     },
     
     /**
     * Edit selected property
     * @param {Ametys.message.MessageTarget} target The property target
     */
     editProperty: function(target)
     {
         var targetParameters = target.getParameters();
         this._workflowName = targetParameters.workflowId;
         this._stepId = targetParameters.stepId;
         this._actionId = targetParameters.actionId;
         this._oldName = targetParameters.name;
         this._mode = "edit";
         var value = targetParameters.value;
         
         Ametys.plugins.workflow.dao.WorkflowPropertyDAO.getPropertiesNames(
             [this._workflowName, parseInt(this._stepId), parseInt(this._actionId)], 
             Ext.bind(this._getPropertiesNamesCB, this, [this._oldName, value], 1)
         ); 
     },
     
     /**
      * @private
      * Callback of getPropertiesNames set form values
      * @param {Object} response list of already used properties names
      * @param {String} name the current property name
      * @param {String} value the current property value
      */
     _getPropertiesNamesCB: function(response, name, value)
     {
         this._unavailableNames = response;
         this._initPropertyBox();
         if (this._mode == "edit")
         {
             this._setPropertyFormValues(name, value);
         }
         else
         {
             this._propertyBox.getComponent('name').reset();
             this._propertyBox.getComponent('value').reset();
         }
         this._propertyBox.show();
     },
          
    /**
     * @private
     * Init the dialog box
     */
    _initPropertyBox: function()
    {
        if (!this._propertyBox)
        {
            this._propertyBox = Ext.create('Ametys.window.DialogBox',  {
                title : this._mode == "new" ? "{{i18n PLUGINS_WORKFLOW_ADD_PROPERTY_DIALOG_TITLE}}" : "{{i18n PLUGINS_WORKFLOW_EDIT_PROPERTY_DIALOG_TITLE}}",
                iconCls: "ametysicon-tag25",
                width:400,
                layout: 'anchor',
                defaultFocus: 'name',
                selectDefaultFocus: true,
                defaults:
                {
                    msgTarget: "side",
                    cls: 'ametys',
                    padding: 5,
                    anchor: '100%',
                    labelAlign: "top",
                    labelSeparator: "",
                    labelStyle: "font-weight:bold",
                },
                items : [
                    {
                        name: 'name',
                        itemId: 'name',
                        xtype:'textfield',
                        allowBlank: false,
                        fieldLabel: "{{i18n PLUGINS_WORKFLOW_ADD_PROPERTY_DIALOG_NAME}} *",
                        ametysDescription: "{{i18n PLUGINS_WORKFLOW_ADD_PROPERTY_DIALOG_NAME_DESC}}",
                        validator: Ext.bind(this._nameValidator, this)
                    },
                    {
                        name: 'value',
                        itemId: 'value',
                        xtype: 'textfield',
                        fieldLabel: "{{i18n PLUGINS_WORKFLOW_ADD_PROPERTY_DIALOG_VALUE}}",
                        ametysDescription: "{{i18n PLUGINS_WORKFLOW_ADD_PROPERTY_DIALOG_VALUE_DESC}}"
                    }
                ],
                
                closeAction: 'hide',
                
                referenceHolder: true,
                defaultButton: 'validate',
                
                buttons : [
                    {
                        reference: 'validate',
                        text: "{{i18n PLUGINS_WORKFLOW_CREATE_DIALOG_OK_BTN}}",
                        handler: Ext.bind(this._ok, this)
                    },
                    {
                        text: "{{i18n PLUGINS_WORKFLOW_CREATE_DIALOG_CANCEL_BTN}}",
                        handler: Ext.bind(this._hideDialogBox, this)
                    }
                ]
            });
        }
        else
        {
            this._propertyBox.setTitle(this._mode == "new" ? "{{i18n PLUGINS_WORKFLOW_ADD_PROPERTY_DIALOG_TITLE}}" : "{{i18n PLUGINS_WORKFLOW_EDIT_PROPERTY_DIALOG_TITLE}}");
        }
    },
    
    _nameValidator: function(newName)
    {
        // New name can't be used by another property
        return newName != this._oldName && this._unavailableNames.includes(newName) 
                    ? "{{i18n PLUGINS_WORKFLOW_ADD_PROPERTY_DIALOG_NAME_ERROR}}" 
                    : true;
    },
    
    /**
     * @private
     * Create property with form values 
     */
    _ok: function ()
    {
        if (this._hasInvalid(this._propertyBox))
        {
            return;
        }
        var newValue = this._propertyBox.getComponent('value').getValue();
        var newName = this._propertyBox.getComponent('name').getValue();
        
        if (this._mode == "new")
        {
            Ametys.plugins.workflow.dao.WorkflowPropertyDAO.addProperty([this._workflowName, parseInt(this._stepId), parseInt(this._actionId), newName, newValue], this._hideDialogBox, {scope: this});
        }
        else
        {
            Ametys.plugins.workflow.dao.WorkflowPropertyDAO.editProperty([this._workflowName, parseInt(this._stepId), parseInt(this._actionId), this._oldName, newName, newValue], this._hideDialogBox, {scope: this});
        }
    },
    
    /**
     * @private
     * Return true if a field is invalid
     * {Ametys.window.DialogBox} the dialog box
     */
    _hasInvalid: function(box)
    {
        var fields = box.query("[isFormField]");
        var hasInvalid = false;
        for (let field of fields)
        {
            if (!field.isValid())
            {
                hasInvalid = true;
            }
        }
        return hasInvalid;
    },
        
     /**
     * Hide the dialog box
     * @param {Object} response the server response
     * @param {String} response.message an error message if defined
     */
    _hideDialogBox: function (response)
    {
        if (!response || !response.message)
        {
            this._propertyBox.hide();
        }
    },
    
    /**
     * @private
     * Set the form's fields initial values
     * @param {String} name the property's name
     * @param {String} value the property's value
     */
    _setPropertyFormValues: function(name, value)
    {
        this._propertyBox.getComponent('name').setValue(name);
        this._propertyBox.getComponent('value').setValue(value);
    },
    
     /**
     * Delete selected property
     * @param {Ametys.message.MessageTarget} target The property target
     */
     deleteProperty: function(target)
     {
         this._oldName = target.getParameters().name;
         Ametys.Msg.confirm("{{i18n PLUGINS_WORKFLOW_EDITION_DELETE_LABEL}}",
            Ext.String.format("{{i18n plugin.workflow:PLUGINS_WORKFLOW_DELETE_PROPERTY_CONFIRM}}", this._oldName),
            Ext.bind(this._doRemove, this, [target], 1),
            this
        );
     },
     
     /**
      * @private
      * Send server request to delete property
      * @param {String} btn The pressed button. Can only be 'yes'/'no'
      * @param {Ametys.message.MessageTarget} target The transition target to remove.
      */
     _doRemove: function(btn, target)
    {
        if (btn == 'yes')
        {
            var targetParameters = target.getParameters();
            this._actionId = targetParameters.actionId;
            this._stepId = targetParameters.stepId;
            this._workflowName = targetParameters.workflowId;
            
            Ametys.plugins.workflow.dao.WorkflowPropertyDAO.deleteProperty([this._workflowName, parseInt(this._stepId), parseInt(this._actionId), this._oldName]);
        }
    }   
});