/*
 *  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 provides a widget to query and select one or more users.
 * 
 * This widget is the default widget registered for fields of type Ametys.form.WidgetManager#TYPE_USER.<br>
 */
Ext.define('Ametys.form.widget.User', {
    extend: 'Ametys.form.AbstractQueryableComboBox',
  
	valueField: 'value',
	displayField: 'displayName',
    
    /**
     * @private
     * @property {String[]} _contexts The contexts for the populations where to retrieve users
     */
    /**
     * @cfg {String[]} [contexts] The contexts for the populations where to retrieve users. Default to the default ametys contexts
     */

    constructor: function(config)
    {
        config = config || {};
        this._contexts = config.contexts ? Ext.Array.from(config.contexts) : Ametys.getAppParameter('populationContexts');
        
        this.callParent(arguments);
    },
	
    getStore: function()
    {
    	if (!Ext.data.schema.Schema.get('default').hasEntity('Ametys.form.widget.User.Users')) {
    		Ext.define("Ametys.form.widget.User.Users", {
    			extend: 'Ext.data.Model',

                idProperty: 'value',

	    		fields: [
	    		         {name: 'firstname', type: 'string'},
	    		         {name: 'lastname', type: 'string'},
	    		         {name: 'login', type: 'string'},
	    		         {name: 'populationId', type: 'string'},
	    		         {name: 'populationLabel', type: 'string'},
                         {
                             name: 'value', 
                             type: 'string',
                             calculate: function(data)
                             {
                            	 return data.login + '#' + data.populationId;
                             }
                          },
	    		         {name: 'fullname', type: 'string'},
	    		         {name: 'sortablename', type: 'string'},
	    		         {
	    		             name: 'displayName',
	    		             type: 'string',
	    		             calculate: function (data)
	    		             {
                                return Ametys.helper.Users.renderUser(data.login, data.populationLabel, data.sortablename);
                             }
	    		         }
	    		]
    		});
    	}

        return Ext.create('Ext.data.Store', {
            model: 'Ametys.form.widget.User.Users',
            proxy: {
                type: 'ametys',
                role: "org.ametys.plugins.core.user.UserDAO",
                methodName: "searchUsersByContexts",
                methodArguments: ['contexts', 'limit', 'offset', 'searchCriteria', 'limitedToStoredUserData'],
                reader: {
                    type: 'json',
                    rootProperty: 'users'
                }
            },
            
            pageSize: this.maxResult,
            sortOnLoad: true,
            sorters: [{property: 'displayName', direction:'ASC'}],
            
            listeners: {
                beforeload: {fn: this._onStoreBeforeLoad, scope: this}
            }
        });
    },
    
    _convertToComparableValue: function(item)
    {
        if (!item)
        {
            return "";
        }
        else if (Ext.isString(item))
        {
            if (!item.startsWith('{'))
            {
                return item;
            }
            item = JSON.parse(item)
        }

        return item.login + '#' + item.populationId;
    },
    
    getValue: function ()
    {
    	var value = this.callParent(arguments),
    		convertedValues = [];
    	
    	value = Ext.Array.from(value);
    	
        var store = this.combobox.valueStore;
            
    	Ext.Array.forEach (value, function (val) {
            var index = store.find('value', val);
            if (index != -1)
            {
                // When editing field from a grid and to render correctly the value, we need populationLabel, sortablename or fullname (see Ametys.helper.Users.renderUser)
                var record = store.getAt(index);
                convertedValues.push({
                    login: record.get('login'),
                    populationId: record.get('populationId'),
                    populationLabel: record.get('populationLabel') || undefined, // undefined for an non existing user, otherwise '' would be considered as a modification by a grid edition
                    sortablename: record.get('sortablename') || undefined,
                    fullname: record.get('fullname') || undefined,
                });
            }
            else
            {
                if (Ext.isString(val))
                {
                    var parts = val.split('#');
    	            convertedValues.push({
    	                login: parts[0],
    	                populationId: parts[1]
    	            });
                }
                else if (val.isModel)
                {
                    convertedValues.push({
                        login: val.get('login'),
                        populationId: val.get('populationId'),
                        populationLabel: val.get('populationLabel') || undefined, // undefined for an non existing user, otherwise '' would be considered as a modification by a grid edition
                        sortablename: val.get('sortablename') || undefined,
                        fullname: val.get('fullname') || undefined
                    });
                }
                else
                {
                    convertedValues.push(Ext.clone(val));
                }
            }
    	});
    	
    	return this.multiple ? convertedValues : convertedValues[0];
    },
    
    setValue: function(value)
    {
    	value = value ? Ext.Array.from(value) : [];
    	
    	var convertedValues = [];
    	Ext.Array.forEach(value, function(item) {
    		if (Ext.isObject(item))
    		{
                let i = Ext.clone(item);
                i.value = i.login + "#" + i.populationId
    			convertedValues.push(i);
    		}
            else if (item == "CURRENT")
            {
                var currentUser = Ametys.getAppParameter("user");
                if (currentUser)
                {
                    let i = Ext.clone(currentUser);
                    i.value = i.login + "#" + i.populationId
                    convertedValues.push(i);
                }
            }
            else
    		{
                var userJson = Ext.JSON.decode(item, true /*safe to return null if it fails*/);
    			if (userJson == null)
    			{
                    // was not a JSON but a raw value
    				convertedValues.push(item);
    			}
    			else
    			{
                    userJson.value = userJson.login + "#" + userJson.populationId
                    convertedValues.push(userJson);
    			}
    		}
    	});
    	
    	this.callParent([convertedValues]);
    },
    
    isEqual: function(val1, val2)
    {
        if (val1 == null && val2 == null)
        {
            return true;
        }
        else if (val1 == null || val2 == null)
        {
            return false;
        }
        else
        {
            return val1.login == val2.login && val1.populationId == val2.populationId;
        }
    },
    
    /**
     * 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.
     * @protected
     */
    _onStoreBeforeLoad: function(store, operation)
    {
        var proxy = operation.getProxy();
        
        proxy.setExtraParam('contexts', this._contexts);
        proxy.setExtraParam('limit', this.maxResult);
        proxy.setExtraParam('offset', 0);
        proxy.setExtraParam('searchCriteria', operation.getParams().query);
    },
    
    getSubmitValue: function ()
    {
    	var value = this.getValue();
    	return value != null ? Ext.encode(this.getValue()) : null;
    },
    
    getLabelTpl: function ()
    {
    	return [
            '<tpl if="!sortablename && !fullname"><span class="a-widget-user-unknown"></tpl>',
            '<img src="{[Ametys.helper.Users.getUserImage(values.login, values.populationId, 16)]}" style="float: left; margin-right: 3px; width: 16px; height: 16px;"/>',
            '{displayName}',
            '<tpl if="!sortablename && !fullname"></span></tpl>'
        ];
    }
});