/*
 *  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.
 */


/**
 * An abstract field displaying the various available profile images 
 */
Ext.define('Ametys.userprefs.UserProfileDialog.ProfileImageField', {
    extend: 'Ametys.form.AbstractField',
    
    /**
     * @property {Ext.view.View} _imagesView The view containing the image entries
     * @private
     */
    
    layout: 'fit',
    
    initComponent: function() 
    {
        this._imagesView = Ext.create('Ext.view.View', Ext.applyIf(this.imagesGridCfg || {}, {
            selModel: {
                mode: 'SINGLE'
            },
            
            overItemCls: 'x-view-over',
            ui: 'view',
            
            scrollable: true,
            
            store: this._getImageStore(),
            tpl: this._getViewTpl(),
            itemSelector: 'div.profile-image',
            border: true,
            style: {borderStyle: 'solid'},
            listeners: {
                beforeselect: {fn: this._onBeforeSelect, scope: this}
            }
        }));
        
        this.items = [this._imagesView];
        
        this.callParent(arguments);
    },
    
    /**
     * @private
     * Get the store used in the images view
     * @return {Ext.data.Store} the store
     */
    _getImageStore: function()
    {
        return Ext.create('Ext.data.Store', {
            model: 'Ametys.userprefs.UserProfileDialog.ProfileImageModel',
            proxy: {
                type: 'ametys',
                plugin: 'core-ui',
                url: 'user-profile/images/list.json',
                reader: {
                    type: 'json',
                    rootProperty: 'images'
                }
            },
            listeners: {
                load: {fn: this._onLoad, scope: this}
            }
        });
    },
    
    /**
     * Public function used to request a load of the store
     * @param {Object} loadArgs arguments to be passed to the load function of the image store
     */
    loadStore: function(loadArgs)
    {
        this._imagesView.getStore().load(loadArgs || {});
    },
    
    /**
     * @private
     * Get the template
     * @return {Ext.XTemplate} The template
     */
    _getViewTpl: function()
    {
        return new Ext.XTemplate(
            '<tpl for=".">',
                '<div class="profile-image{[values.source == "upload-image" ? " unselectable" : ""]}">',
                    '<img src="{viewUrl}" data-qtip="{description}" style="width:64px; height:64px;">',
                '</div>',
            '</tpl>'
        );
    },
    
    getValue: function()
    {
        var selected = this._imagesView.getSelectionModel().getSelection()[0];
        if (selected)
        {
            var value = {
                source: selected.get('source')
            };
            
            var parameters = selected.get('parameters');
            if (Ext.isObject(parameters) && !Ext.Object.isEmpty(parameters))
            {
                value.parameters = parameters;
            }
            
            return value;
        }
        else
        {
            return null;
        }
    },
    
    setValue: function(value)
    {
        // retrieves the value object
        value = value || null;
        if (value)
        {
            if (Ext.isString(value))
            {
                value = Ext.JSON.decode(value);
            }
            
            // value should be an object at this point
            if (!Ext.isObject(value))
            {
                value = null;
            }
        }
        
        var store = this._imagesView.getStore();
        if (!store.isLoaded())
        {
            this._valueToSet = value;
        }
        else
        {
            var index = this._findByValue(value);
            if (index >= 0)
            {
                this._imagesView.getSelectionModel().select(index);

                var record = store.getAt(index);
                var node = this._imagesView.getNode(record);
                node.click();
            }
        }
    },
    
    /**
     * Handler called when the store has loaded
     * @param {Ext.data.Store} store the field's store
     * @param {Ext.data.Model[]} records An array of records
     * @param {Boolean} successful True if the operation was successful.
     */
    _onLoad: function(store, records, successful)
    {
        if (successful)
        {
            // Set value if needed
            if (this._valueToSet)
            {
                var index = this._findByValue(this._valueToSet);
                if (index >= 0)
                {
                    this._imagesView.getSelectionModel().select(index);
                    
                    var record = store.getAt(index);
                    var node = this._imagesView.getNode(record);
                    node.click();
                }
                
                this._valueToSet = null;
            }
            
            // Insert the upload icon
            var store = this._imagesView.getStore();
            
            store.insert(0, {
                source: 'upload-image'
            });
        }
    },
    
    /**
     * Retrieves the index of a record corresponding to a value object
     * @return {Object} The value corresponding to a record (key are source and parameters)
     */
    _findByValue: function(value)
    {
        var store = this._imagesView.getStore();
        
        return store.findBy(function(record) {
            var source = record.get('source');
            
            if ((value.source == 'base64') && (source == value.source))
            {
                return true; // special case when value is stored in the userpref
            }
            
            if (source == value.source)
            {
                var recordParams = record.get('parameters') || {},
                    valueParams = value.parameters || {};
                
                return Ext.Object.equals(recordParams, valueParams);
            }
        });
    },
    
    /**
     * @param {Ext.selection.DataViewModel} model The data view model
     * @param {Ext.data.Model} record The selected record.
     * @param {Number} index The index within the store of the selected record.
     */
    _onBeforeSelect: function(model, record, index)
    {
        if (record.get('source') == 'upload-image')
        {
            Ametys.helper.FileUpload.open({
                iconCls: 'ametysicon-image2',
                title: "{{i18n PLUGINS_CORE_UI_USER_PREFERENCES_PROFILE_IMAGE_FILE_UPLOAD_TITLE}}",
                helpmessage: "{{i18n PLUGINS_CORE_UI_USER_PREFERENCES_PROFILE_IMAGE_FILE_UPLOAD_HINT}}",
                callback: Ext.bind(this._fileUploadCb, this),
                filter: Ametys.helper.FileUpload.IMAGE_FILTER
            });
            
            return false;
        }
    },
    
    /**
     * Callback function to be executed after a file has been uploaded.
     * @param {String} id The file id.
     * @param {String} fileName The file name
     * @param {Number} fileSize The file size in bytes.
     * @return The HTML described file
     */
    _fileUploadCb: function(id, fileName, fileSize)
    {
        // Insert just after the upload icon.
        var index = 1;
        var inserted = this._imagesView.getStore().insert(1, {
            source: 'upload',
            parameters: {
                id: id
            }
        });
        
        this._imagesView.getSelectionModel().select(inserted[0]);
        
        var record = this._imagesView.getStore().getAt(1);
        var node = this._imagesView.getNode(record);
        node.click();
    }
});