/*
 *  Copyright 2015 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 class provides a widget to query and select one or more metadata set.
 */
Ext.define('Ametys.cms.form.widget.MetadataSet', {
    extend: 'Ametys.form.widget.ComboBox',
    
    /**
     * @cfg {String} [defaultValue=abstract] The widget default value
     */
    defaultValue: 'abstract',
    
    /**
     * @cfg {Boolean} [includeInternals] True to show internal views
     */
    /**
     * @private
     * @property {Boolean} _includeInternals The property related to {@link #cfg-includeInternals}
     */
    /**
     * @cfg {String} [contentTypesField] The relative path the content types
     *      field, to allow the list of metadataset to be updated given the
     *      value of the content types field
     */
    /**
     * @private
     * @property {String} _contentTypesFieldName The property related to {@link #cfg-contentTypesField}
     */
    /**
     * @cfg {String} [contentsField] The relative path the content field, to
     *      allow the list of metadataset to be updated given the value of the
     *      content field
     */
    /**
     * @private
     * @property {String} _contentsFieldName The property related to {@link #cfg-contentsField}
     */
	/**
     * @cfg {String} [contentTypeId] The id of content type, to load the list of 
	 * 	  	available metadataset given this value
     */
    /**
     * @private
     * @property {String} _contentTypeId The property related to {@link #cfg-contentTypeId}
     */
    
    /**
     * @cfg {String} [plugin=cms] The name of plugin used to retrieve common views list.
     */
    plugin: 'cms',
    /**
     * @cfg {String} [url=common-views.json] The url used to retrieve common views list.
     */
    url: 'common-views.json',
    
    constructor: function (config)
    {
        config.valueField = 'name';
        config.displayField = 'label';
        
        config.typeAhead = false;
        config.editable = false;
        
        config.proxyStore = {
            type: 'ametys',
            plugin: this.plugin,
            url: this.url,
            reader: {
                type: 'json',
                rootProperty: 'views'
            }
        };
        
        this.callParent(arguments);
        
        this._includeInternals = config.includeInternals || false;
        this._contentTypesFieldName = config.contentTypesField || null;
        this._contentsFieldName = config.contentsField || null;
		this._contentTypeId = config.contentTypeId || null;
        
        this.form.onRelativeFieldsChange([this._contentTypesFieldName, this._contentsFieldName], this, this._relativeFieldChange);
		
		if (this._contentTypeId)
        {
            this.form.executeFormReady(() => {this.getStore().load()}, this);
        }
    },
    
    /**
     * Get the store configuration
     * @param {Object} config The current configuration object
     * @return {Object} The store configuration
     */
    getStoreCfg: function(config)
    {
        var storeCfg = this.callParent(arguments);

        Ext.apply(storeCfg, {
            sortOnLoad: true,
            listeners: {
                beforeload: {fn: this._onStoreBeforeLoad, scope: this},
                load: {fn: this._onStoreLoad, scope: this}
            }
        });
        
        return storeCfg;
    },
    
    /**
     * Set the request parameters before loading the store.
     * @param {Ext.data.Store} store The store.
     * @param {Ext.data.operation.Operation} operation The Ext.data.Operation object that will be passed to the Proxy to load the Store.
     * @private
     */
    _onStoreBeforeLoad: function(store, operation)
    {
        var relativeFields = this.form.getRelativeFields([this._contentTypesFieldName, this._contentsFieldName], this),
            contentTypesField = relativeFields[0],
            contentsField = relativeFields[1];
        
        var params = operation.getParams() || {};
        operation.setParams(Ext.apply(params, {
            includeInternals: this._includeInternals,
            ids: contentTypesField ? contentTypesField.getValue() : this._contentTypeId,
            contentIds: contentsField ? contentsField.getValue() : null
        }));
    },
    
    /**
     * Set the value after the store load
     * @param {Ext.data.Store} store The store.
     * @param {Ext.data.Model[]} records The loaded records.
     * @private
     */
    _onStoreLoad: function(store, records)
    {
        if (this.allowBlank && !this.multiple)
        {
            // Add a space to label to force first place while sorting
            store.add({name: '', label: ' ' + this.emptyText});
        }
        
        if (this._needReload)
        {
            // new reload is needed (because of a relative field change)
            this._needReload = false;
            this._relativeFieldChange();
            
            // At the end of this load the value will be lost (not part of the store) so we need to re-set it
            var me = this,
                originalValue = this.getValue();
            setTimeout(function() {
                me.setValue(originalValue);
            }, 1)
        }
        else
        {
	        var value = this.getValue(),
	            store = this.getStore();
                
	        if (store.find(this.valueField, value) != -1)
	        {
	            // Nothing to do, the value is already correct
	            // this.setValue(value);
	        }
	        else if (store.find(this.valueField, this.defaultValue) != -1)
	        {
	            this.setValue(this.defaultValue);
	        }
	        else
	        {
	            this.reset();
	        }
        }
    },
    
    /**
     * Listener called when the value of a relative field changes
     */
    _relativeFieldChange: function()
    {
        if (this.getStore().isLoading())
        {
            this._needReload = true;
        }
        else
        {
	        this.getStore().load();
        }
    }
});