/*
 *  Copyright 2016 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.
 */

/**
 * Content context for profile assignments.
 */
Ext.define('Ametys.plugins.cms.profiles.ContentRightAssignmentContext', {
    extend: 'Ametys.plugins.coreui.profiles.AbstractRightAssignmentContext',
    
    /**
     * @property {String} DEFAULT_MODEL_ID The default id of the search model
     * @readonly
     */
    DEFAULT_MODEL_ID: "search-ui.right-assignment",
    
    /**
     * @cfg {String} [modelId] The id of the search model. If not provided, {@link #DEFAULT_MODEL_ID} will be used.
     */
    /**
     * @private
     * @property {String} _modelId The id of the search model
     */
    
    /**
     * @private
     * @property {Ext.container.Container} _container The component of this right assignment context
     */
    /**
     * @private
     * @property {Ametys.form.ConfigurableFormPanel} _form The form of the search criteria
     */
    /**
     * @private
     * @property {Ext.grid.Panel} _grid The result grid
     */
    /**
     * @private
     * @property {Ext.data.Store} _gridStore The store of the grid
     */
    
    /**
     * @private
     * @property {Boolean} _initialized true if the criteria and the result grid are initialized
     */
    _initialized: false,
    
    /**
     * @private
     * @property {String} _contentsRootContext The context holding the contents
     */
    _contentsRootContext: null,
    
    /**
     * @cfg {String} [radio-option-all-label] The label to display in the option for assign on all contents
     */
    /**
     * @private
     * @property {String} _radioOptionAllLabel The label to display in the option for assign on all contents
     */
    
    /**
     * @cfg {String} [hint-all-contents] The hint to display when the option 'radio-content-all' is selected
     */
    /**
     * @private
     * @property {String} _hintAllContents The hint to display when the option 'radio-content-all' is selected
     */
    
    /**
     * @cfg {String} [result-grid-mask-message] The message of the mask in the result grid when the option 'radio-content-all' is selected
     */
    /**
     * @private
     * @property {String} _resultGridMaskMessage The message of the mask in the result grid when the option 'radio-content-all' is selected
     */
    
    constructor: function(config)
    {
        this.callParent(arguments);
        
        this._modelId = config.modelId || this.DEFAULT_MODEL_ID;
        this._radioOptionAllLabel = config['radio-option-all-label'] || "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_RADIO_OPTION_ALL}}";
        this._hintAllContents = config['hint-all-contents'] || "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_HINT_ALL}}";
        this._resultGridMaskMessage = config['result-grid-mask-message'] || "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_MASK_MESSAGE}}";
        this._contentsRootContext = config['root-context'];
    },
    
    getComponent: function()
    {
        var items = this._getRadioFields();
        
        // Form containing the search criteria
        this._form = this._createForm();
        
        // The result grid
        this._grid = this._createSearchGrid();
        
        items.push({
            xtype: 'container',
            itemId: 'search-container',
            flex: 1,
            layout: {
                type: "vbox",
                align: "stretch"
            },
            items: [this._form, this._grid]
        }); 
        
        this._container = Ext.create('Ext.container.Container', {
            layout: {
                type: "vbox",
                align: "stretch"
            },
            items: items,
            
            listeners: {
                destroy: Ext.bind(function(ct) {
                    this._initialized = false;
                }, this)
            }
        });
        return this._container;
    },
    
    /**
     * @private
     * Get the radio fields items
     * @return The radio fields
     */
    _getRadioFields: function()
    {
        return [{
                xtype: 'radiofield',
                boxLabel  : this._radioOptionAllLabel,
                name      : 'radio-content',
                itemId: 'radio-content-all',
                checked: true,
                inputValue: 'all',
                style: {
                    marginLeft: '5px'
                }
            }, {
                xtype: 'radiofield',
                boxLabel  : "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_RADIO_OPTION_SEARCH}}",
                name      : 'radio-content',
                inputValue: 'search',
                itemId: 'radio-content-search',
                handler: this._onSelectSearch,
                scope: this,
                style: {
                    marginLeft: '5px'
                }
        }];
    },
    
    /**
     * @private
     * Create a form
     * @return The form
     */
    _createForm: function()
    {
        // Form containing the search criteria
        return Ext.create('Ametys.form.ConfigurableFormPanel', {
            defaultFieldConfig: {
                labelWidth: 110
            }
        });
    },
    
    /**
     * @private
     * Create the search result grid
     * @return The grid
     */
    _createSearchGrid: function ()
    {
    	// The store of the result grid
        this._gridStore = Ext.create('Ext.data.Store', {
            remoteSort: true,
            autoLoad: false,
            sortOnLoad: true,
            listeners: {
                'beforeload': {fn: this._onBeforeLoadGrid, scope: this},
                'load': {fn: this._onLoadGrid, scope: this}
            }
        });
        
    	return Ext.create('Ext.grid.Panel', {
            store: this._gridStore,
            scrollable: true,
            width: '100%',
            flex: 1,
            listeners: {
                'selectionchange': Ext.bind(this._onSelectionChanged, this)
            },
            
            selModel : {
                mode: 'MULTI'
            },
            
            dockedItems: [{
                dock: 'top',
                xtype: 'toolbar',
                layout: {
                    type: 'hbox',
                    align: 'stretch'
                },
                border: true,
                items: [{
                    itemId: 'search',
                    text: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH}}",
                    iconCls: 'ametysicon-magnifier12',
                    handler: this._search,
                    scope: this,
                    tooltip: {
                        title: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH}}",
                        text: "{{i18n plugin.cms:UITOOL_SEARCH_BUTTON_SEARCH_DESC}}",
                        glyphIcon: 'ametysicon-magnifier12',
                        inribbon: false
                    }
                }]
            }, {
                dock: 'bottom',
                xtype: 'pagingtoolbar',
                store: this._gridStore,
                displayInfo: true,
                displayMsg: "{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_RESULT_1}}{0}{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_RESULT_2}}{1}{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_RESULT_3}}{2}",
                emptyMsg: "{{i18n plugin.cms:UITOOL_CONTENTEDITIONGRID_NO_RESULT}}",
                scrollable: true
            }]
        });
    },
    
    /**
     * @private
     * Handler when the search radio button is checked or unchecked
     */
    _onSelectSearch: function (checkbox, checked)
    {
    	if (checked)
    	{
    		// Enable search
    		this._switchToSearchMode();
    	}
    	else
    	{
    		// Disable search
    		this._switchToAllContentsMode();
    	}
    },
    
    initialize: function()
    {
        if (!this._initialized)
        {
            // Retrieve the search model
            Ametys.data.ServerComm.callMethod({
                role: "org.ametys.cms.search.model.SearchModelHelper",
                methodName: "getSearchModelConfiguration",
                parameters: [this._modelId, this._getContextualParameters()],
                callback: {
                    handler: this._getSearchModelCb,
                    scope: this
                },
                errorMessage: {
                    msg: "{{i18n UITOOL_SEARCH_ERROR}}",
                    category: Ext.getClassName(this)
                },
                waitMessage: {
                    msg: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_LOADMASK_DEFAULT_MESSAGE}}",
                    target: this._container
                }
            });
        }
        else
        {
            this._switchToAllContentsMode();
        }
    },
    
    /**
     * @private
     * Switch to the "all contents" mode
     */
    _switchToAllContentsMode: function()
    {
    	this._container.down('#radio-content-all').setValue(true);
    	this._changeObjectContext(this._contentsRootContext, "<b>" + this._hintAllContents + "</b>", false, true);
    	
    	// Disable search result grid
    	this._grid.getSelectionModel().deselectAll();
    	var searchContainer = this._container.down('#search-container');
        searchContainer.mask(this._resultGridMaskMessage, 'ametys-mask-unloading');
    },
    
    /**
     * @private
     * Switch to search mode
     */
    _switchToSearchMode: function ()
    {
    	var searchContainer = this._container.down('#search-container');
    	searchContainer.unmask();
    	
        this._initSearchGrid(this._grid);
    },
    
    /**
     * @private
     * Initialize a search grid
     * @param {Ext.grid.Panel} grid the grid
     */
    _initSearchGrid: function(grid)
    {
        if (grid.getStore().getData().length > 0)
        {
            var firstRecord = grid.getStore().getData().getAt(0);
            grid.getSelectionModel().select(firstRecord);
        }
        else
        {
            this._changeObjectContext(null, null, false, true);
        }
    },
    
    /**
     * @protected
     * Get the contextual parameters used to get search model and search results.
     * @return {Object} the contextual parameters
     */
    _getContextualParameters: function()
    {
        return {
            language: this._getCurrentLanguage()
        };
    },
    
    /**
     * @private
     * Provides the current language to be used.
     * @return {String} The current language
     */
    _getCurrentLanguage: function()
    {
        return Ametys.cms.language.LanguageDAO.getCurrentLanguage();
    },
    
    /**
     * @protected
     * Get the default values to put in the search model
     * @return {Object} The values 
     */
    _getDefaultSearchValues: function()
    {
        return {};
    },
    
    /**
     * @private
     * After retrieving the search model, configure the form and the result columns
     * @param {Object} result The server result
     */
    _getSearchModelCb: function(result)
    {
        // Configure the search form
        this._form.configure(result['simple-criteria']);
        this._form.setValues(this._getDefaultSearchValues());
        
        // Reconfigure the result grid
        var fields = Ametys.plugins.cms.search.SearchGridHelper.getFieldsFromJson(result.columns);
        Ametys.plugins.cms.search.ContentSearchTool.addDefaultContentFields(fields);
        var columns = Ametys.plugins.cms.search.SearchGridHelper.getColumnsFromJson(result.columns, false);
        var sorters = Ametys.plugins.cms.search.SearchGridHelper.getSortersFromJson(columns, this._grid);
        
        this._gridStore.setProxy({
            type: 'ametys',
            plugin: result.searchUrlPlugin,
            url: result.searchUrl,
            reader: {
                type: 'json',
                rootProperty: 'contents'
            }
        });
        
        if (result.pageSize != null && result.pageSize > 0)
        {
            this._gridStore.setPageSize(result.pageSize);
        }
        
        // Update model
        this._gridStore.model.replaceFields(fields, true);
        this._grid.reconfigure(columns);
        this._gridStore.setSorters(sorters); // Will fire a load event
        
        this._switchToAllContentsMode();
        this._initialized = true;
    },
    
    /**
     * @private
     * Function called before loading the grid store
     * @param {Ext.data.Store} store The grid store
     * @param {Ext.data.operation.Operation} operation The object that will be passed to the Proxy to load the store
     */
    _onBeforeLoadGrid: function(store, operation)
    {
    	if (!this._initialized)
    	{
    		return false;
    	}
    	
        operation.setParams(Ext.apply(operation.getParams() || {}, {
            values: Ext.clone(this._form.getJsonValues()),
            excludeSubContents: false,
            model: this._modelId,
            contextualParameters: this._getContextualParameters()
        }));
    },
    
    /**
     * @private
     * Function called when loading the grid store
     * @param {Ext.data.Store} store The grid store
     * @param {Ext.data.Model[]} records The loaded records
     * @param {Boolean} successful True if the operation was successful.
     * @param {Ext.data.operation.Operation} operation The object that will be passed to the Proxy to load the store
     */
    _onLoadGrid: function(store, records, successful, operation)
    {
        if (successful && !operation.aborted && records.length > 0)
        {
            this._grid.getSelectionModel().select(records[0]);
            this._grid.getView().focusRow(0);
        }
    },
    
    /**
     * @private
     * Listener when the selection in the tree has changed
     * @param {Ext.selection.Model} model The selection model
     * @param {Ext.data.Model[]} selected The selected records
     */
    _onSelectionChanged: function(model, selected)
    {
        if (selected.length > 0)
        {
            if (selected.length == 1)
            {
                var object = selected[0].get('id'),
                title = selected[0].get('title');
                this._changeObjectContext(object, "{{i18n PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_HINT_CONTENT}} <b>" + Ext.String.escapeHtml(title) + "</b>");
            }
            else
            {
                var objects = selected.map(function (item) {
	               return item.get('id');
	            })
                this._changeObjectContext(objects, null);
            }
            
        }
        else if (!this._container.down('#radio-content-all').getValue())
        {
        	this._changeObjectContext(null, null, false, true);
        }
    },
    
    /**
     * @private
     * Launches the search
     * @param {Ext.button.Button} button The button
     */
    _search: function(button)
    {
        if (!this._form.isValid())
        {
            return;
        }
        
        this._gridStore.loadPage(1);
    }
});