/*

 *  Copyright 2021 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 carts in READ access for current user
 * @private
 */
Ext.define('Ametys.plugins.cart.tool.CartsPanel', {
    extend: 'Ext.grid.Panel',
    
	/**
	 * @property {Ext.data.Store} _store The cart store
	 * @private
	 */

    /**
     * @cfg {String} profile The profile ('read_access' or 'right_access') filter. By default, if null, the server will treat the request as 'read_access'
     */    
     
     /**
     * @cfg {Boolean} enableDrop Enable drag and drop process to drop elements into cart
     */
    
    statics: {
        /**
         * Function to render query's title in result grid
         * @param {Object} title The data title
         * @param {Object} metaData A collection of metadata about the current cell
         * @param {Ext.data.Model} record The record
         * @private
         */
        renderWithTooltip: function(value, metaData, record)
        {
            metaData.tdAttr = Ametys.plugins.cart.tool.CartsPanel.descriptionTooltip(record);
            return value;
        },
        
        /**
         * Function to generate description tooltip
         * @param {Ext.data.Model} record The record
         * @private
         */
        descriptionTooltip: function(record)
        {
            return 'data-qtip="<strong>' + record.get("title").replaceAll('"', '&quot;') + '</strong>'
                + (record.get("description") && record.get("description") !== '' ? '<br/>' + record.get("description").replaceAll('"', '&quot;') : '')
                + (record.get("documentation") && record.get("documentation") !== '' ? '<br/>' + Ametys.plugins.cart.tool.CartsPanel.renderDocumentation(record.get("documentation"), null, record).replaceAll('"', '&quot;') : '')
                + '"';
        },
        
        /**
         * Function to render cart's documentation in result grid
         * @param {Object} title The data title
         * @param {Object} metaData A collection of metadata about the current cell
         * @param {Ext.data.Model} record The record
         * @private
         */
        renderDocumentation: function(documentation, metaData, record)
        {
            return '<a href="' + documentation + '" target="_blank">' + documentation + '</a>';
        }
    },
    
    constructor: function(config)
    {
        if (config.enableDrop)
        {
            config.viewConfig = config.viewConfig || {};
            Ext.apply(config.viewConfig, {
                plugins: {
                    ptype: 'ametysgridviewdragdrop',
                    dragTextField: 'title',
                    setAmetysDropZoneInfos: Ext.bind(this.getDropInfo, this)
                }
            });
        }

        config.store = this.createStore(config);
        config.scrollable = true;
        config.cls = 'carts-uitool';
        config.columns = [
            {header: "{{i18n PLUGINS_CART_UITOOL_CARTS_COLUMN_TITLE}}", width: 180, sortable: true, dataIndex: 'title', renderer: Ametys.plugins.cart.tool.CartsPanel.renderWithTooltip},
            {header: "{{i18n PLUGINS_CART_UITOOL_CARTS_COLUMN_DESCRIPTION}}", hidden: false, width: 180, sortable: true, dataIndex: 'description', renderer: Ametys.plugins.cart.tool.CartsPanel.renderWithTooltip},            
            {header: "{{i18n PLUGINS_CART_UITOOL_CARTS_COLUMN_DOCUMENTATION}}", hidden: true, width: 180, sortable: true, dataIndex: 'documentation', renderer: Ametys.plugins.cart.tool.CartsPanel.renderDocumentation},
            {header: "{{i18n PLUGINS_CART_UITOOL_CARTS_COLUMN_AUTHOR}}", hidden: false, width: 110, sortable: true, dataIndex: 'authorFullName'},
            {header: "{{i18n PLUGINS_CART_UITOOL_CARTS_COLUMN_CONTRIBUTOR}}", hidden: false, width: 110, sortable: true, dataIndex: 'contributorFullName'},
            {header: "{{i18n PLUGINS_CART_UITOOL_CARTS_COLUMN_CREATIONDATE}}", hidden: true, width: 110, sortable: true, dataIndex: 'creationDate', renderer: Ext.util.Format.dateRenderer(Ext.Date.patterns.FriendlyDateTime)},
            {header: "{{i18n PLUGINS_CART_UITOOL_CARTS_COLUMN_LASTMODIFICATIONDATE}}", hidden: true, width: 110, sortable: true, dataIndex: 'lastModificationDate', renderer: Ext.util.Format.dateRenderer(Ext.Date.patterns.FriendlyDateTime)}
        ];
        config.selModel = {
                mode: 'MULTI'
        };
        config.features = [{
            ftype:'grouping', 
            
            groupHeaderTpl: Ext.create('Ext.XTemplate',
                '{name:this.formatName}',
                {
                    formatName: function(name) 
                    {
                        switch (parseInt(name)) 
                        {
                            case 0:
                                return "{{i18n PLUGINS_CART_UITOOL_CARTS_GROUP_PERSONAL_CARTS}}";
                            case 1:
                                return "{{i18n PLUGINS_CART_UITOOL_CARTS_GROUP_SHARED_CARTS}}";
                            default: 
                                return name;
                        }
                    }
                }
            )
        }];
        config.cls = this;
        
        // Filter
       config.dockedItems = [{
                dock: 'top',
                xtype: 'toolbar',
                layout: {
                    type: 'hbox',
                    align: 'stretch'
                },
                
                border: false,
                defaults : {
                    cls: 'ametys',
                    labelWidth: 55,
                    labelSeparator: ''
                },
                
                items: [
                    {
                    // Filter input
                    xtype: 'textfield',
                    itemId: 'search-filter-input',
                    cls: 'ametys',
                    flex: 1,
                    maxWidth: 300,
                    emptyText: "{{i18n PLUGINS_CART_UITOOL_CARTS_FILTER_EMPTY_TEXT}}",
                    enableKeyEvents: true,
                    msgTarget: 'qtip',
                    listeners: {change: Ext.Function.createBuffered(this._filterByRegexp, 300, this)}
                }, {
                    // Clear filter
                    tooltip: "{{i18n PLUGINS_CART_UITOOL_CARTS_FILTER_CLEAR}}",
                    handler: Ext.bind (this._clearFilter, this),
                    iconCls: 'a-btn-glyph ametysicon-eraser11 size-16',
                    cls: 'a-btn-light'
                }]
            }]
        
        
        this.callParent(arguments);
        
        Ametys.message.MessageBus.on(Ametys.message.Message.CREATED, this._onCartCreated, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.MODIFIED, this._onCartUpdated, this);
        Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onCartDeleted, this);
    },
        
    /**
     * Creates the cart store
     * @param {Object} config The configuration
     * @param {String} [config.profile=null] See {@link #cfg-profile}
     */
    createStore: function(config)
    {
        var profile = config.profile;
        
        if (!this._store)
        {
            this._store = Ext.create('Ext.data.Store', {
                model: 'Ametys.plugins.cart.tool.CartsTool.CartEntry',
                sorters: [{property: 'title', direction:'ASC'}],
                groupField: 'group',
                
                proxy: {
                    type: 'ametys',
                    plugin: 'cart',
                    url: 'carts/list.json',
                    reader: {
                        type: 'json',
                        rootProperty: 'carts'
                    },
                    extraParams: {
                        profile: profile
                    }
                },
                autoLoad: true
            });
        }
        
        return this._store;
    },
    

    onDestroy: function()
    {
        Ametys.message.MessageBus.unAll(this);
        this.callParent(arguments);
    },
    
    /**
     * @private
     * This event is thrown before the beforeDrop event and create the target of the drop operation relation.
     * @param {Ext.data.Model[]} targetRecords The target records of the drop operation.
     * @param {Object} item The default drag data that will be transmitted. You have to add a 'target' item in it: 
     * @param {Object} item.target The target (in the relation way) of the drop operation. A Ametys.relation.RelationPoint config. 
     */ 
    getDropInfo: function(targetRecords, item)
    {
        if (targetRecords.length > 0)
        {
            var targets = [];
            
            Ext.each (targetRecords, function (record) {
                if (record.get('canWrite'))
                {
                    targets.push({
                        id: Ametys.message.MessageTarget.CART,
                        parameters: {
                            id: record.get('id')
                        }
                    });
                }
            });
            
            item.target = {
                relationTypes: [Ametys.relation.Relation.REFERENCE], 
                targets: targets
            };
        }
    },
    
    /**
     * @private
     * Filters carts by input field value.
     * @param {Ext.form.Field} field The field
     */
    _filterByRegexp: function (field)
    {
        var value = Ext.String.trim(field.getValue());
        if (this._filterValue == value)
        {
            // Do nothing
            return;
        }
        
        this._filterValue = value;
        
        if (value)
        {
            var regexFilter = new RegExp(value, 'i');
            var currentSelection = this.getSelection();
           
            this._store.clearFilter();
            this._store.filterBy(function(record){
                return regexFilter.test(record.data.title) || regexFilter.test(record.data.description) || regexFilter.test(record.data.documentation);
            });
            
            if (currentSelection.length > 0)
            {
                var me = this;
                Ext.Array.each(currentSelection, function (sel) {
                    if (me._store.findExact(me._store.getModel().idProperty, sel.getId()) == -1)
                    {
                        // The current selection is not visible, clear the selection
                        me.getSelectionModel().deselect([sel]);
                    }
                })
                
            }
        }
        else
        {
            // We do not call _clearFilter that will also empty the filter and prevent from typing
            this._filterValue = null;
            this._store.clearFilter(); 
        }
    },
    
    /**
     * @private
     * Clear the current filter
     */
    _clearFilter: function()
    {
        this._filterValue = null;
        this.down("#search-filter-input").reset();
    },
    
    /**
     * Listener when carts have been created
     * Will set the tool in "out of date" mode
     * @param {Ametys.message.Message} message The creation message.
     * @private
     */
    _onCartCreated: function(message)
    {
        var targets = message.getTargets(Ametys.message.MessageTarget.CART);
        
        if (targets.length > 0)
        {
            this.getStore().reload()
        }
    },
    
    /**
     * Listener when carts have been edited
     * Will set the tool in "out of date" mode
     * @param {Ametys.message.Message} message The edition message.
     * @private
     */
    _onCartUpdated: function(message)
    {

        var targets = message.getTargets(Ametys.message.MessageTarget.CART);
        
        if (targets.length > 0)
        {
            this.getStore().reload()
        }
    },
    
    /**
     * Listener when carts have been deleted
     * Will remove the records if present
     * @param {Ametys.message.Message} message The deletion message.
     * @private
     */
    _onCartDeleted: function (message)
    {
        var targets = message.getTargets(Ametys.message.MessageTarget.CART);
        if (targets.length > 0)
        {
            var ids = Ext.Array.map(targets, function(target) {
                return this.getStore().getById(target.getParameters().id);
            }, this);
            
            this.getStore().remove(ids);
        }
    }
});