/*
 *  Copyright 2018 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.
 */
 
 /**
 * Search field widget
 * This widget is registered for fields of type Ametys.form.WidgetManager#TYPE_STRING
 */
Ext.define('Ametys.web.form.widget.SearchField', {
    extend: 'Ametys.form.widget.OrderableTagField',
    mixins: { servercaller: 'Ametys.data.ServerCaller' },
    
    /**
     * @cfg {String} storeMethodName the name of the method for the store
     */
    /**
     * @cfg {String/String[]} fieldsReloadingWidget the names of the fields (separated by ',') which will launch a reload of this widget when their value change
     */
    
    getServerRole: function()
    {
        return "org.ametys.core.ui.widgets.WidgetsManager";
    },
    
    getServerId: function()
    {
        return "edition.search-field";
    },
    
    /**
     * @protected
     * The model name for the store
     * @return {String} model name for the store
     */
    getStoreModel: function()
    {
        return 'Ametys.web.form.widget.SearchFacet.Model';
    },
    
    constructor: function(config)
    {
        config = Ext.apply(config, {
            store: {
                autoDestroy: true,
                model: this.getStoreModel(),
                proxy: {
                    type: 'ametys',
                    serverCaller: this,
                    methodName: config.storeMethodName,
                    reader: {
                        type: 'json'
                    }
                 },
                listeners: {
                    'beforeload': this._onBeforeLoad,
                    scope: this
                }
            },
            
            multiSelect: config.multiple,
            queryMode: 'local'
        });
        this.callParent(arguments);
    },
    
    initComponent: function()
    {
        if (this.form && Ext.isFunction(this.form.onRelativeFieldsChange))
        {
            // returnables will launch the reinit when it will change
            this.form.onRelativeFieldsChange('returnables', this, this._reinitStore);
            
            // given fields will launch the reinit when they will change
            var fieldsReloadingWidget = this.getInitialConfig('fieldsReloadingWidget');
            fieldsReloadingWidget = Ext.isArray(fieldsReloadingWidget) ? fieldsReloadingWidget : fieldsReloadingWidget.split(',');
            Ext.Array.forEach(fieldsReloadingWidget, function(fieldName) {
                this.form.onRelativeFieldsChange(fieldName, this, this._reinitStore);
            }, this);
        }
        
        this.callParent(arguments);
    },
    
    /**
     * @private
     * Function invoked right before the store is loaded
     * @param {Ext.data.Store} store the store
     * @param {Ext.data.operation.Operation} operation The {@link Ext.data.operation.Operation} object that will be passed to the Proxy to load the Store
     */
    _onBeforeLoad: function(store, operation)
    {
        operation.setParams(Ext.apply(operation.getParams() || {}, {
            returnableIds: this.form.getField('returnables').getValue(),
            formValues: this.form.getJsonValues()
        }));
    },
    
    /**
     * @private
     * Reinitialize the store
     */
    _reinitStore: function()
    {
        this.getStore().load({
            scope: this,
            callback: function(records, operation, success) {
                var valueToSet = Ext.Array.from(this.value).filter(Ext.bind(this._isInStore, this));
                this.setValue(valueToSet);
            }
        });
    },
    
    /**
     * @protected
     * Filter function to determine if a record associated to a given value (as a string) is in store 
     * @param {String} valueAsStr the string value
     * @return {Boolean} True if a record associated to the given value string is in store
     */
    _isInStore: function(valueAsStr)
    {
        return this.getStore().indexOfId(valueAsStr) > -1;
    },
    
    getValue: function()
    {
        // tag field now always returns multiple values, but that's not fine for our widgets
        var value = this.callParent(arguments);
        return this.multiple ? value : (value && value.length > 0 ? value[0] : null);
    }
});

/**
 * @private
 * The model used in the {@link Ametys.web.form.widget.SearchField} store 
 */
Ext.define('Ametys.web.form.widget.SearchFacet.Model', { 
    extend: 'Ext.data.Model',
    
    idProperty: 'value',
    fields: [
        'value',
         {
            name: 'text', type: 'string',
            calculate: function(data) {
                if (data.groupText)
                {
                    return data.groupText + ' > ' + data.shortText;
                }
                return data.shortText;
            }
         },
         {name: 'groupText', type: 'string'},
         {name: 'shortText', type: 'string'}
    ]
});