/*
 *  Copyright 2025 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 allows to search elements in the trash.
 */
Ext.define('Ametys.plugins.cms.trash.TrashSearchTool', {
    extend: 'Ametys.plugins.cms.search.AbstractFacetedSearchTool',

    constructor: function(config)
    {
        this.callParent(arguments);
        Ametys.message.MessageBus.on(Ametys.message.Message.DELETED, this._onMessageDeleted, this);
    },
    
    getMBSelectionInteraction: function()
    {
        return Ametys.tool.Tool.MB_TYPE_ACTIVE;
    },
    
    _onSelectionChanged: function(sm, selected)
    {
        this.sendCurrentSelection();
    },
    
    sendCurrentSelection: function()
    {
        Ext.create('Ametys.message.Message', {
            type: Ametys.message.Message.SELECTION_CHANGED,
            targets: this.grid.getSelectionModel().getSelection().map(sel => ({
                id: Ametys.message.MessageTarget.TRASH_ELEMENT,
                parameters: {
                    id: sel.getId(),
                    title: sel.get('title'),
                    type: sel.get('trashType_enum')[sel.get('trashType')].label
                }
            }))
        });
    },
    
    _getStoreCfg: function()
    {
        // The proxy of this store is automatically configured in the _configureProxy method
        return {
            remoteSort: true,
            sortOnLoad: true,
             
            listeners: {
                'beforeload': {fn: this._onBeforeLoad, scope: this},
                'load': {fn: this._onLoad, scope: this}
            }
        };
    },

    _getReaderCfg: function()
    {
        return {
            type: 'json',
            rootProperty: 'items',
            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;
    },
    
    /**
     * 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);
            }
        }
        
        if (records.length == 0)
        {
            this.grid.getView().mask("{{i18n plugin.cms:UITOOL_SEARCH_PAGEBAR_NO_RESULT}}", 'ametys-mask-unloading');
        }
        
        this._setGridDisabled(false);
    },

    _retrieveCriteriaAndColumns: function(force)
    {
        Ametys.data.ServerComm.callMethod({
            role: "org.ametys.cms.trash.TrashManager",
            methodName: "getSearchModel",
            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, this.getParams());
    },
    
    /**
     * Listener when trash elements have been deleted
     * Will set the tool in "out of date" mode
     * @param {Ametys.message.Message} message The message.
     * @protected
     */
    _onMessageDeleted: function (message)
    {
        let params = message.getParameters();
        if (params && params.trashed)
        {
            // Something has been added to the trash
            this.showOutOfDate();
        }
        else
        {
            let targets = message.getTargets(Ametys.message.MessageTarget.TRASH, 1); // No need to dig subtargets
            // The trash has been emptied
            if (targets.length > 0)
            {
                this.showOutOfDate();
            }
            // Only some elements have been deleted
            else
            {
                targets = message.getTargets(Ametys.message.MessageTarget.TRASH_ELEMENT, 1); // No need to dig subtargets
                if (targets.length > 0)
                {
                    Ext.Array.forEach(
                        targets, 
                        function(target) {
                            let record = this.store.getById(target.getParameters().id);
                            this.grid.getSelectionModel().deselect([record]);
                            this.store.remove(record);
                        },
                        this
                    );
                }
            }
        }
    }
});

Ext.define("Ametys.message.TrashMessageTarget", {
    override: "Ametys.message.MessageTarget",

     statics: 
     {
        /**
         * @member Ametys.message.MessageTarget
         * @readonly
         * @property {String} TRASH The target is the trash.
         */
        TRASH: "trash",
        
         /**
          * @member Ametys.message.MessageTarget
          * @readonly
          * @property {String} TRASH_ELEMENT The target is a trash element. The expected parameters are:
          * @property {String} TRASH_ELEMENT.id The id of the trash element
          * @property {String} TRASH_ELEMENT.title The title of the trash element
          * @property {String} TRASH_ELEMENT.type The label of type of the trash element
          */
         TRASH_ELEMENT: "trash-element"
     }
});