/*
 *  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 a global consistency report for contents which consistency
 * issues.
 * @private
 */
Ext.define('Ametys.plugins.cms.content.tool.GlobalContentConsistencyTool', {
    extend: "Ametys.plugins.cms.search.AbstractFacetedSearchTool",
    
    statics: {
        renderContentType: function(value, _metaData, _record, _rowIndex, _colIndex, _store, _view, _dataIndex)
        {
            if (Ext.isEmpty(value) || Ext.Object.isEmpty(value))
            {
                return '';
            }
            
            var values = Ext.Array.from(value);
        
            var html = '';
            for (var i=0; i < values.length; i++)
            {
                var cTypeValue = values[i];
                var label = cTypeValue.label;
                var smallIcon = cTypeValue.smallIcon;
                var iconGlyph = cTypeValue.iconGlyph;
                var iconDecorator = cTypeValue.iconDecorator;
                
                if (!Ext.isEmpty(html))
                {
                    html += '<br/>';
                }
                
                if (iconGlyph)
                {
                    html += `<span class="a-grid-glyph ${iconGlyph} ${iconDecorator ? " " + iconDecorator : ""}"></span>${label}`
                }
                // use small icon as fallback
                else
                {
                    html += `<img src="${Ametys.CONTEXT_PATH + smallIcon}" class="a-grid-icon"/>${label}`;
                }
            }
            
            return html;
        }
    },
    
    constructor: function()
    {
        this.callParent(arguments);

        Ametys.message.MessageBus.on(Ametys.message.Message.TASK_ENDED, this._onTaskEnded, this);
    },
    
    _onTaskEnded: function(message)
    {
        var taskTarget = message.getTarget(Ametys.message.MessageTarget.TASK);
        if (taskTarget != null && taskTarget.getParameters().schedulable == "org.ametys.web.content.consistency.CheckContentConsistencySchedulable");
        {
            this.showOutOfDate();
        }
    },
    
    getMBSelectionInteraction: function() 
    {
        return Ametys.tool.Tool.MB_TYPE_ACTIVE;
    },
    
    // Open contistency tool at the opening
    onOpen: function ()
    {
        this.callParent (arguments);
        // Try to open the check consistency tool if available
        if (Ametys.tool.ToolsManager.getFactory('uitool-consistency'))
        {
            Ametys.tool.ToolsManager.openTool ('uitool-consistency');
        }
    },

    
    /**
     * @protected
     * Get the config to be used to create the store.
     * @return {Object} The config object
     */
    _getStoreCfg: function()
    {
        return {
            remoteSort: true,
            sortOnLoad: true,
             
            listeners: {
                'beforeload': {fn: this._onBeforeLoad, scope: this},
                'load': {fn: this._onLoad, scope: this}
            }
        };
    },
    
    _getResultGridCfg: function(store)
    {
        var cfg = this.callParent (arguments);
        return Ext.Object.merge(cfg, {
            listeners: {
                'itemdblclick': {fn: function (view, record, item, index, e) { this.openContent(record); }, scope: this}
            }
        })
    },
    
    openContent: function(record)
    {
        Ametys.tool.ToolsManager.openTool('uitool-content', {'id' : record.get('contentId')});
    },
    
    /**
     * 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
     * @protected
     */
    _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;
            }
            
            operation.setParams( Ext.apply(operation.getParams() || {}, {
                model: this._modelId,
                values: this.form.getJsonValues()
            }));
            
            // Facet handling
            this.facetValues = this._faceting ? this.getFacetValues() : {};
            operation.setParams(Ext.apply(operation.getParams(), {
                facetValues: this.facetValues,
            }));
            
            this._facets = null;
        }
        else
        {
            // avoid use less requests at startup (applyState...)
            return false;
        }
    },
    
    _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);
        
        // Load facet store
        if (this.facetPanel.isVisible() && this._facets)
        {
            if (!this._faceting)
            {
                // TODO Create a brand new memory proxy with the data and set it, instead of just changing the 'data' property?
                this.facetPanel.getStore().getProxy().setData(this._facets);
                this.facetPanel.getStore().load();
                this.facetPanel.getRootNode().expand();
            }
            else
            {
                this._updateFacetPanel(this._facets);
            }
        }
        
        this._setGridDisabled(false);
    },
    
    /**
     * @protected
     * Implement this method with your own logic for retrieving information about search criteria and columns.
     * It should call {@link #_configureSearchTool}, either directly, or as a callback function after a server call, so as to finish the process of drawing and configure the search tool.
     * @param {Boolean} force True to force the update of the model and columns even if not needed
     */
    _retrieveCriteriaAndColumns: function(force)
    {
        Ametys.data.ServerComm.callMethod({
            role: "org.ametys.cms.content.consistency.ContentConsistencySearcher",
            methodName: "getModel",
            callback: {
                handler: this._getSearchModelCb,
                scope: this,
            },
            errorMessage: {
                msg: "{{i18n plugin.cms:UITOOL_SEARCH_ERROR}}",
                category: Ext.getClassName(this)
            }
        });
    },
    
    _getSearchModelCb: function(result)
    {
        this._configureSearchTool({"fieldsetForDisplay" : {elements : result['criteria'], role: "fieldset"}}, result, {});
    },
    
    /**
     * @protected
     * Get the config to be used to create the reader for the store.
     * @return {Object} The config object
     */
    _getReaderCfg: function()
    {
        return {
            type: 'json',
            rootProperty: 'consistencyResults',
            transform: {
                fn: this._transformSearchData,
                scope: this
            }
        };
    },
    
    /**
     * Transform search data before loading it. Used to extract facet results.
     * @param data {Object} The original data object.
     * @return {Object} The transformed data object.
     * @private
     */
    _transformSearchData: function(data)
    {
        this._facets = data.facets;
        
        // Return the data untouched.
        return data;
    },
    
    /**
     * @protected
     * Listener when the selection has changed in result grid.
     * @param {Ext.selection.Model} sm the selection model
     * @param { Ext.data.Model[]} selected the selected record
     */
    _onSelectionChanged: function(sm, selected)
    {
        this.sendCurrentSelection(selected);
    },
    
    sendCurrentSelection: function(selection)
    {
        if (selection == null)
        {
            selection = this.grid.getSelectionModel().getSelection();
        }
        var contentIds = Ext.Array.map(selection, function(record) {
            return record.get("contentId");
        });
        
        Ext.create("Ametys.message.Message", {
            type: Ametys.message.Message.SELECTION_CHANGED,
            
            targets: {
                id: Ametys.message.MessageTarget.CONTENT,
                parameters: { ids: contentIds }
            }
        });
    },
    
        /**
     * Get the JS parameters for export
     * @return {Object} the parameters
     */
    getSearchParametersForExport: function ()
    {
        var params = {}
        params.values = this.form.getJsonValues();
        
        params.columns = this._getExportColumns();
        
        params.sort = this.getEncodedSortersForExport() || undefined;
        params.model = this._modelId;
        
        params.facetValues = this.getFacetValues();
        
        return params;
    },
    
    /**
     * Get the array of current active sorters.
     * @return {String} The list of sorters. Entry of the list are object with keys 'property' and 'direction' (optionnal)
     */
    getCurrentSorters: function()
    {
        var sorters = [];
        this.store.getSorters().each (function (sorter) {
            sorters.push({property: sorter.getProperty(), direction: sorter.getDirection()})
        });
        return sorters;
    },
    
    /**
     * Get the JSON encoded array of sorters.
     * @return {String} A JSON String representing the list of sorters. Entry of the list are object with keys 'property' and 'direction' (optionnal)
     */
    getEncodedSortersForExport: function()
    {
        return Ext.encode(this.getCurrentSorters() || []);
    },
    
    /**
     * Get the list of columns to export
     * @return {String[]} The id of columns in a Array
     */
    _getExportColumns: function()
    {
        var columns = [];
        Ext.Array.forEach(this.grid.getColumns(), function (column) {
            if (column.dataIndex && column.isVisible())
            {
                columns.push(column.dataIndex);
            }
        });
        return columns;
    }
});