/*
 *  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.
 */
/**
 * Class defining the property grid panel for workflow elements
 */
 Ext.define('Ametys.plugins.workflow.grids.PropertyGridPanel', {
     extend: 'Ext.grid.Panel',
     
    constructor: function(config)
    {
        config.store = (config.elementType == "step")? this._getStepPropertyStore() : this._getTransitionPropertyStore();
        var plugins = config.plugins;
        config.plugins = Ext.isArray(plugins) ? plugins : (plugins == null ? [] : [plugins]);
        config.plugins.push({
            ptype: 'cellediting',
            clicksToEdit: 1,
            editAfterSelect: true,
            listeners: {
                'beforeedit': Ext.bind(this._onBeforeEdit, this),
                'edit': Ext.bind(this._onEdit, this)
            }
        });
        this.callParent(arguments);
    },
    
    /**
     * Set the grid parameters
     * @param {String} workflowName unique name of the current workflow
     * @param {Number} stepId the id of current step
     * @param {Number} actionId the id of current action
     */
    initGridParameters(workflowName, stepId, actionId)
    {
        this._workflowName = workflowName,
        this._stepId = stepId;
        this._actionId = actionId;
    },
    
    /**
     * Create the step property grid's store
     * @returns {Ext.data.Store} a Ext.data.Store as the store of this _stepPropertyGrid
     * @private
     */
    _getStepPropertyStore: function()
    {
        return Ext.create('Ext.data.Store', {
            model: 'Ametys.plugins.workflow.models.PropertiesGridModel', 
            proxy: {
                type: 'ametys',
                role: 'org.ametys.plugins.workflow.dao.WorkflowPropertyDAO',
                methodName: 'getStepProperties',
                methodArguments: ["workflowName", "stepId"],
                reader: {
                    type: 'json',
                    rootProperty: 'data'
                }
             },
             sorters: [{property: 'id', direction: 'ASC' }],
             listeners: {
                 'beforeload': {fn: this._onStepBeforeLoad, scope: this},
                 'load': {fn: this._onPropertyGridLoad , scope: this }
             }
        });
    },
    
    /**
     * Create the action property grid's store
     * @returns {Ext.data.Store} a Ext.data.Store as the store of this _transitionPropertyGrid
     * @private
     */
    _getTransitionPropertyStore: function()
    {
        return Ext.create('Ext.data.Store', {
            model: 'Ametys.plugins.workflow.models.PropertiesGridModel', 
            proxy: {
                type: 'ametys',
                role: 'org.ametys.plugins.workflow.dao.WorkflowPropertyDAO',
                methodName: 'getActionProperties',
                methodArguments: ["workflowName", "actionId"],
                reader: {
                    type: 'json',
                    rootProperty: 'data'
                }
             },
             sorters: [{property: 'id', direction: 'ASC' }],
             listeners: {
                 'beforeload': {fn: this._onActionBeforeLoad, scope: this},
                 'load': {fn: this._onPropertyGridLoad , scope: this }
             }
        });
    },
    
    /**
     * Function called before loading a transition grid store
     * @param {Ext.data.Store} store The store
     * @param {Ext.data.operation.Operation} operation The object that will be passed to the Proxy to load the store
     * @private
     */
    _onActionBeforeLoad: function(store, operation)
    {
        operation.setParams(Ext.apply(operation.getParams() || {}, {
            workflowName: this._workflowName,
            actionId: parseInt(this._actionId)
        }));
    },
        
    /**
     * Function called before loading step grids stores
     * @param {Ext.data.Store} store The store
     * @param {Ext.data.operation.Operation} operation The object that will be passed to the Proxy to load the store
     * @private
     */
    _onStepBeforeLoad: function(store, operation)
    {
        operation.setParams(Ext.apply(operation.getParams() || {}, {
            workflowName: this._workflowName,
            stepId: parseInt(this._stepId)
        }));
    },
    
    /**
     * Listener on property grid store load, display number of rows in the panel's title and collapse the grid if it's empty
     * @param {Ext.data.Store} store the store being loaded
     * @param {Object[]} records the store content
     * @private
     */
    _onPropertyGridLoad: function(store, records)
    {
        if (records.length == 0) // if grid has no rows
        {
            this.collapse();
        }
        else
        {
            this.expand();
        }
        this.setTitle(this.getInitialConfig('title') + " ("+ records.length + ")");
    },
    
    /**
     * @private
     * Listener called before cell editing 
     * @param {Ext.grid.plugin.CellEditing} editor The cell editor
     * @param {Object} context An editing context event with the following properties:
     * @param {Ext.data.Model} context.record The record being edited.
     * @param {String} context.field The name of the column being edited
     */
    _onBeforeEdit: function(editor, context)
    {
        return context.field == "value";
    },
    /**
     * @private
     * Listener called after cell editing
     * @param {Ext.grid.plugin.CellEditing} editor The cell editor
     * @param {Object} context An editing context with the following properties:
     * @param {Ext.data.Model} context.record The record being edited.
     * @param {Mixed} context.value The field's current value.
     * @param {Mixed} context.originalValue The original value before being edited.
     */
    _onEdit: function(editor, context)
    {
        var record = context.record,
            newValue = context.value,
            oldValue = context.originalValue;
        
        if (newValue != oldValue)
        {
            var name = record.getData().id;
            Ametys.plugins.workflow.dao.WorkflowPropertyDAO.editProperty([this._workflowName, parseInt(this._stepId), parseInt(this._actionId), name, name, newValue], renameCb)
        }
        
        var grid = this;
        function renameCb(response)
        {
            if (!response || response.message)
            {
                // it failed
                record.beginEdit()
                record.set('text', oldValue);
                record.endEdit();
                record.commit();
            }
            
            grid.getSelectionModel().deselectAll();
            grid.getSelectionModel().select(record);
            
        }
    }
 });
 
/**
* Define the model for the meta properties
*/
Ext.define('Ametys.plugins.workflow.models.PropertiesGridModel', {
    extend: 'Ext.data.Model',
    
    fields: [
        {name: 'id', type: 'string'},
        {name: 'value', type: 'string'}
    ]
});