/*
 *  Copyright 2013 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 is used to select a mention.<br>
 * The content type for mention depends on the selected degree.<br>
 * 
 * Use {@link #cfg-degreeFieldPath} to set the relative path of degree field in the form.<br>
 */
Ext.define('Ametys.odf.widget.Mention', {
    extend : 'Ametys.cms.form.widget.SelectReferenceTableContent',
    
    statics: {
        
        /**
         * @property {String} ABSTRACT_MENTION_TYPE The id of abstract mention type
         * @readonly
         * @type String
         */
        ABSTRACT_MENTION_TYPE: 'odf-enumeration.Mention'
    },
    
    /**
     * @cfg {String} degreeFieldPath The relative path of degree field. This field determines the type of mentions.
     */
    
    /**
     * @property {String} _degreeFieldPath See #{cfg-degreeField}
     */
    
    /**
     * @private
     * @property {Object} _degreeCache The cache for degrees
     */
    _degreeCache: {},
    
    /**
     * @private
     * @property {String} _mentionContentType The mention content type
     */
    _mentionContentType: null,
    
    
    constructor: function (config)
    {
        this._mentionContentType = Ametys.odf.widget.Mention.ABSTRACT_MENTION_TYPE;
        
        this.callParent(arguments);
        
        this._degreeFieldPath = config.degreeFieldPath;
        if (this._degreeFieldPath && this.form && Ext.isFunction(this.form.onRelativeFieldsChange))
        {
            this.form.onRelativeFieldsChange([this._degreeFieldPath], this, this._onDegreeFieldChange);
        }
    },
    
    /**
     * @private
     * Listener when the field holding the degree change
     * @param {Ext.form.Field} field The degree field
     */
    _onDegreeFieldChange: function(field)
    {
        // At initialization, field.getValue() can return null whereas field.value is not empty,
        // because degree field is initialized asynchronously.
        // Note that field.value can be an invalid or unknow id but it will be filtered by #getMentionContentTypes call
        var value = field.getValue() || field.value;
        
        // in case of externalizable field
        value = Ametys.form.widget.Externalizable.getValueInUse(value);
        
        // handle of multiple values
        value = Ext.isArray(value) ? value : (Ext.isEmpty(value) ? [] : [value]); 
        
        if (value.length > 0)
        {
            var mentionType = null; 
            
            // Inspect each degree values
            for (var i=0; i < value.length; i++)
            {
                if (this._degreeCache[value[i]] === undefined)
	            {
                    // At least one degree value was not find in cache, ask to server for all degree values
	                Ametys.data.ServerComm.callMethod({
		                role: "org.ametys.odf.enumeration.OdfReferenceTableHelper",
		                methodName: "getMentionContentTypes",
		                parameters: [value],
		                callback: {
		                    handler: this._getMentionContentTypeCb,
		                    scope: this
		                },
		                waitMessage: false
		            });
                    return;
	            }
                else if (mentionType == null && this._degreeCache[value[i]] != null)
                {
                    // Retains the first non-null mention type obtained from the cache
                    mentionType = this._degreeCache[value[i]];
                }
            }
            
            // Here the mention type was obtained from the cache (but can be null)
            if (mentionType != this._mentionContentType)
            {
                this._updateMentionType(mentionType);
            }
        }
        else
        {
            this._updateMentionType(null);
        }
    },
    
    /**
     * @private
     * Callback function after retrieving the content types for each selected degrees 
     * @param {String[]} mentionTypes The mention's content types. Can be null.
     * @param {Object} args The callback arguments
     */
    _getMentionContentTypeCb: function(mentionTypes, args)
    {
        var mentionType = null;
        
        // Populate cache and get the first non-null mention type
        for (var degreeId in mentionTypes)
        {
            this._degreeCache[degreeId] = mentionTypes[degreeId];
            if (mentionType == null && mentionTypes[degreeId] != null)
            {
                mentionType = mentionTypes[degreeId];
            }
        }
        
		if (mentionType != this._mentionContentType)
        {
            this._updateMentionType(mentionType);
        }
    },
    
    /**
     * @private
     * Update the content type 
     * and reset the value and store of this field
     * @param {String} mentionType The new mention type. Can be null.
     */
    _updateMentionType: function(mentionType)
    {
        var oldMentionType = this._mentionContentType;
        this._mentionContentType = mentionType;
        this.modelId = "reference-table-search-ui." + this._mentionContentType;
        this.contentType = this._mentionContentType;
        
        // Reset the last query to allow store to be reload on trigger click !
        this.combobox.lastQuery = undefined;
        
        if (oldMentionType != Ametys.odf.widget.Mention.ABSTRACT_MENTION_TYPE)
        {
            // The type of mention has changed, clear values and store
            // at initialization the content type is the abstract mention type, the current value should not be removed
	        this.setValue();
	        this.combobox.getStore().removeAll();
        }
    },
    
    _onStoreBeforeLoad: function(store, operation)
    {
        if (!this._mentionContentType)
        {
            // No mention for the current degree
            return false;
        }
        
        this.callParent(arguments);
    }
});