/*
 *  Copyright 2022 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 the list of temporary users, awaiting for subscription's finalization.
 */
Ext.define('Ametys.plugins.web.tempusers.TempUsersTool', {
    extend: 'Ametys.plugins.cms.search.AbstractSearchTool',
    
     
    constructor: function(config)
	{
		this.callParent(arguments);
        
        Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onTempUserDeleted, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onTempUserCreatedOrModified, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onTempUserCreatedOrModified, this);
	},
	
	getMBSelectionInteraction: function()
    {
        return Ametys.tool.Tool.MB_TYPE_ACTIVE;
    },
    
    createStore: function()
    {
        var storeCfg = Ext.applyIf(this._getStoreCfg(), {
            autoDestroy: true,
            pageSize: Ametys.plugins.cms.search.AbstractSearchTool.PAGE_SIZE
        });
        
        return Ext.create('Ext.data.Store', storeCfg);
    },
    
    _getStoreCfg: function()
    {
        return {
            model: 'Ametys.plugins.web.tempusers.TempUsersTool.TempUser',
            proxy: {
                type: 'ametys',
                methodName: 'searchTempUsers',
                methodArguments: ['siteName', 'searchParameters', 'start', 'limit', 'sorters'],
                role: 'org.ametys.web.usermanagement.UserSignupManager',
                reader: {
                   type: 'json',
                   rootProperty: 'users'
                },
                extraParams: {
                    siteName: Ametys.getAppParameter('siteName')
                }
            },
            
            sorters: [{property: 'email', direction:'ASC'}],
            remoteSort: true,
            sortOnLoad: true,
            
            listeners: {
                'beforeload': {fn: this._onBeforeLoad, scope: this},
                'load': Ext.bind(this._onLoad, this)
            }
        }
    },
    
    // Overriden to enable multi selection
    _getResultGridCfg: function(store)
    {
        var dockedItems = [];
        if (this.enablePagination)
        {
            dockedItems.push(this._getPaginationToolbarCfg(store));
        }
        
        return { 
            store: store,
            
            region: 'center',
            split: true,
            border: false,
            
            stateful: true,
            stateId: this.getId() + "$grid",
            
            columns: [], // columns will be set later
            
            selModel : {
                mode: 'MULTI'
            },
            
            features: [{
                ftype: 'grouping',
                groupHeaderTpl: [
                    '{columnName}: {name:this.formatName}',
                    {
                        formatName: function(name) {
                            return Ext.String.trim(name.toString());
                        }
                    }
                ]
            }],
            
            viewConfig: {
                loadingText: "{{i18n plugin.cms:UITOOL_SEARCH_WAITING_MESSAGE}}"
            },
            
            dockedItems: dockedItems,
            
            listeners: {
                'selectionchange': Ext.bind(this._onSelectionChanged, this)
            }
        };
    },
    
    /**
     * Function called before loading the 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
     */
    _onBeforeLoad: function(store, operation)
    {
        if (this.grid && !this._updatingModel && (!(this.form instanceof Ametys.form.ConfigurableFormPanel) ||  this.form.isFormReady()))
        {
            this.grid.getView().unmask();
            
            if (!this.form.isValid())
            {
                this._stopSearch();
                return false;
            }
            
            var sorters = [];
            this.store.getSorters().each (function (sorter) {
                var sortProperty = sorter.getProperty();
                var direction = sorter.getDirection();
                if (sortProperty == 'expiration_date')
                {
                    sortProperty = "subscription_date";
                }
                else if (sortProperty == 'expired')
                {
                    sortProperty = "subscription_date";
                    direction = direction == 'ASC' ? 'DESC' : 'ASC';
                }
                
                sorters.push({property: sortProperty, direction: direction})
            });
            
            var values = this.form.getJsonValues();
            if (values.population && values.population == '#all')
            {
                values.population = null;
            }
            
            operation.setParams( Ext.apply(operation.getParams() || {}, {
               'searchParameters': values,
               'sorters': sorters
            }));
            
            this._error = null;
        }
        else
        {
            // avoid use less requests at startup (applyState...)
            return false;
        }
    },
    
    /**
     * Function called after loading results
     * @param {Ext.data.Store} store The store
     * @param {Ext.data.Model[]} records An array of records
     * @param {Boolean} successful True if the operation was successful.
     * @param {Ext.data.operation.Operation} operation Operation performed by the proxy
     * @protected
     */
    _onLoad: function (store, records, successful, operation)
    {
        if (operation.aborted)
        {
            // Load has been canceled. Do nothing.
            return;
        }
        
        // Hack to process groups locally even if remoteSort is enabled.
        store.getData().setAutoGroup(true);
        
        this._setGridDisabled(false);
        
        if (records.length == 0)
        {
            this.grid.getView().mask("{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_NO_RESULT}}", 'ametys-mask-unloading');
        }
        
        this.sendCurrentSelection();
    },
    
    _onSelectionChanged: function(sm, selected)
    {
        this.sendCurrentSelection();
    },
    
	sendCurrentSelection : function()
	{
		var targets = [];
        var store = this.grid.getStore();
        
        var emails = [];
        
        var selection = this.grid.getSelectionModel().getSelection();
        for (var i=0; i < selection.length; i++)
        {
            emails.push(selection[i].data.email);
        }
        
        Ext.create("Ametys.message.Message", {
            type: Ametys.message.Message.SELECTION_CHANGED,
            
            targets: {
                id: Ametys.message.MessageTarget.TEMP_USER,
                parameters: { emails: emails }
            }
        });
	},
    
    refresh: function()
    {
        Ametys.plugins.web.tempusers.TempUsersDAO.invalidateCache();
        
        this.callParent(arguments);
    },
    
    _retrieveCriteriaAndColumns: function(force)
    {
        var toolParams = this.getParams().toolParams || {};
        
        var criteria = this._getSearchCriteria();
        
        this._configureSearchForm(criteria);
        
        var columns = this._getColumns();
        
        this.grid.reconfigure(this.store, columns);
        
        this._initSearchForm(toolParams);
        
        this._updatingModel = false;
        
        // Launch search
        this.refresh();
    },
    
    /**
     * @protected
     * Get the search criteria configuration
     * @return the search criteria
     */
    _getSearchCriteria: function()
    {
        return {
            "criteria": {
                role: 'fieldset',
                elements: {
		            "pattern": this._getTextfieldCfg(),
		            "population": this._getPopulationComboboxCfg(),
		            "origin": this._getOriginComboboxCfg()
		        }
            }
            
        }
    },
    
    /**
     * @protected
     * Get the columns configuration
     * @return The array of columns
     */
    _getColumns: function()
    {
        return [
                {stateId: 'grid-email', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_EMAIL}}", flex: 1, minWidth : 160, sortable: true, dataIndex: 'email'},
                {stateId: 'grid-firstname', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_FIRSTNAME}}", width : 180, sortable: true, dataIndex: 'firstname'},
                {stateId: 'grid-lastname', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_LASTNAME}}", width : 180, sortable: true, dataIndex: 'lastname'},
                {stateId: 'grid-population', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_POPULATION}}", width : 200, sortable: true, dataIndex: 'population', renderer: this._renderPopulation},
                {stateId: 'grid-userDirectory', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_USER_DIRECTORY}}", width : 180, sortable: true, hidden: true, dataIndex: 'userDirectory', renderer: this._renderUserDirectory},
                {stateId: 'grid-subscriptionDate', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_SUBSCRIPTION_DATE}}", width : 160, sortable: true, dataIndex: 'subscription_date', renderer: Ext.util.Format.dateRenderer('d F Y')},
                {stateId: 'grid-expirationDate', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_EXPIRATION_DATE}}", width : 160, sortable: true, dataIndex: 'expiration_date', renderer: Ext.util.Format.dateRenderer('d F Y')},
                {stateId: 'grid-origin', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_ORIGIN}}", width : 160, sortable: true, dataIndex: 'origin', renderer: Ext.bind(this._renderOrigin, this)},
                {stateId: 'grid-status', header: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_EXPIRED_STATUS}}", width : 140, hidden: false, sortable: true, dataIndex: 'expired', renderer: Ext.bind(this._renderExpired, this)}
        ];
    },
    
    /**
     * @private
     */
    _getOriginComboboxCfg: function()
    {
        return {
                label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_ORIGIN}}",
                widget: 'edition.combobox',
                type: "boolean",
                enumeration: [
                    {
                        value: null,
                        label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_ORIGIN_ALL}}"
                    },
	                {
	                    value: 'INVITATION',
	                    label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_ORIGIN_FROM_INVITATION}}"
	                },
	                {
	                    value: 'USER_REQUEST',
	                    label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_ORIGIN_FROM_USER_REQUEST}}"
	                }
                ]
            }
    },
    
    /**
     * @private
     */
    _getTextfieldCfg: function()
    {
        return {
            label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_TEXTFIELD}}",
            type: "string",
            
            'widget-params': {
                emptyText: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_TEXTFIELD_EMPTY_TEXT}}"
            }
        }
    },
    
    /**
     * @private
     */
    _getPopulationComboboxCfg: function()
    {
        return {
            widget: 'edition.combobox',
            label: "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_CRITERIA_POPULATION}}",
            type: "string",
            
            'widget-params': {
                valueField: 'id',
	            displayField: 'label',
	            forceSelection: true,
	            triggerAction: 'all',
                defaultValue: '#all',
		            
	            proxyStore: {
	                type: 'ametys',
	                plugin: 'core-ui',
	                url: 'populations.json',
	                reader: {
	                    type: 'json',
	                    rootProperty: 'userPopulations'
	                },
                    extraParams: {
                        contexts: Ametys.getAppParameter('populationContexts'),
                        modifiable: true // only modifiable
                    }
	            },
                
                storeListeners: {
                    'load': {fn: this._onLoadPopulations, scope: this}
                }
            }
        };
    },
    
    /**
     * @private
     * Listener invoked after loading populations
     * @param {Ext.data.Store} store The store
     * @param {Ext.data.Model[]} records The records of the store
     */
    _onLoadPopulations: function(store, records)
    {
        // Add an option in the populations combobox for searching over all the populations
        store.add({
            id: '#all',
            label: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_TOOL_USERS_POPULATION_FIELD_OPTION_ALL}}"
        });
    },
    
    /**
     * @private
     * Render the expired column of the grid
     * @param {String} value the value of 'expired'
     */
    _renderExpired: function (value)
    {
        if (value)
        {
            return '<span class="a-grid-glyph ametysicon-sign-raw-cross"></span>' + " {{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_STATUS_EXPIRED}}";
        }
        
        return '<span class="a-grid-glyph ametysicon-datetime-clock"></span>' + " {{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_STATUS_ACTIVE}}";
    },
    
     /**
     * @private
     * Render the signup request origin
     * @param {String} value the value of 'origin'
     */
    _renderOrigin: function(value)
    {
        if (value == 'INVITATION')
        {
            return "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_ORIGIN_FROM_INVITATION}}";
        }
        else if (value == 'USER_REQUEST')
        {
            return "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_ORIGIN_FROM_USER_REQUEST}}";
        }
        else
        {
            return "{{i18n PLUGINS_WEB_USERS_TEMP_UITOOL_COL_ORIGIN_UNKNOWN}}";
        }
    },
    
    /**
     * @private
     * Render the population
     * @param {String} value the id of population
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     */
    _renderPopulation: function(value, metaData, record)
    {
        return record.get("populationLabel") || value;
    },
    
    /**
     * @private
     * Render the user directory
     * @param {String} value the id of user directory
     * @param {Object} metaData A collection of metadata about the current cell
     * @param {Ext.data.Model} record The record
     */
    _renderUserDirectory: function(value, metaData, record)
    {
        return record.get("userDirectoryLabel") || value;
    },
    
	/**
     * @private
     * Listener upon reception of a creation message 
     * @param {Ametys.message.Message} message the creation message
     */
    _onTempUserCreatedOrModified: function(message)
    {
        var targets = message.getTargets(Ametys.message.MessageTarget.TEMP_USER);
        if (targets.length > 0)
        {
            this.showOutOfDate(true);
        }
    },
    
    /**
     * @private
     * Listener upon reception of a deletion message
     * @param {Ametys.message.Message} message the deletion message
     */
    _onTempUserDeleted: function(message)
    {
        var targets = message.getTargets(Ametys.message.MessageTarget.TEMP_USER);
        if (targets.length > 0)
        {
            var store = this.grid.getStore();
            Ext.Array.forEach(targets, function(target) {
                var email = target.getParameters().email;
                var index = store.find("email", email); 
                if (index != -1)
                {
                    store.removeAt(index);
                }
            });
        }
    }
});