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

/**
 * This UI helper provides a dialog box to choose a glyph from a given store.
 * See #open method.
 */
Ext.define('Ametys.helper.ChooseGlyph', {
	singleton: true,
	
	/**
     * @property {Ametys.window.DialogBox} _box The dialog box
     * @private
     */

	/**
     * @property {Ext.form.field.Text} _filterField The filter field for glyph
     * @private
     */
	
    /**
     * @property {Ext.view.View} _dataView The data view for glyph
     * @private
     */
	
	/**
     * @private
	 * @property {Function} _cbFn The callback function invoked when glyph are selected
	 */
	
	/**
     * Configure and open the dialog box
     * @param {Object} config The configuration options :
     * @param {Object} config.storeCfg (required) The store configuration
     * @param {Object} config.storeCfg.proxy (required) The proxy to use for the store
     * @param {Object} [config.storeCfg.model=Ametys.helper.ChooseGlyph.Model] The name of the model associated to this store
     * @param {String} [config.iconCls] The CSS class for the icon of the dialog box.
     * @param {String} [config.title] The title of the dialog box.
     * @param {String} [config.helpMessage] The help message to display on top of dialog box.
     * @param {Function} config.callback The callback function invoked when a glyph is selected. The callback function will received the following parameters:
     * @param {Object} config.callback.glyph The name of selected glyph
     */
	open: function (config)
	{
		this._cbFn = config.callback;
        this._createDialogBox(config.title, config.iconCls, config.helpMessage);
        this._initDialog(config.storeCfg);
    	this._box.show();
	},
	
	/**
     * @private
	 * Creates the dialog box
     * @param {String} [title] The title of the dialog box.
	 * @param {String} [iconCls] The CSS class for the icon of the dialog box.
     * @param {String} [helpMessage] The help message to display on top of dialog box.
	 */
	_createDialogBox: function(title, iconCls, helpMessage)
	{
		if (!this._initialized)
		{
			this._dataView = this._createDataView();
			this._filterField = this._createFilterField();
		    
			this._box = Ext.create('Ametys.window.DialogBox', {
				title: title || "{{i18n PLUGINS_CORE_UI_WIDGET_HELPER_CHOOSEGLYPH_DIALOG_TITLE}}",
		        width: 450,
		        height: 350,
                layout: {
			        type: 'vbox',
                    align: 'stretch'
			    },
		        scrollable: false,
		        alwaysOnTop: true,
		        referenceHolder: true,
		        closeAction: 'hide',
		        iconCls: iconCls || 'ametysicon-puzzle33',
                cls: 'choose-glyph-helper',
		        
		        items: [
		        	{
		        		xtype: "component",
		        		cls: "a-text",
		        		html: helpMessage || "{{i18n PLUGINS_CORE_UI_WIDGET_HELPER_CHOOSEGLYPH_DIALOG_HINT}}"
		        	},
		        	this._filterField,
	                this._dataView
		        ],
		        
		        buttons: [{
		        	reference: 'validate',
		            text: "{{i18n PLUGINS_CORE_UI_WIDGET_HELPER_CHOOSEGLYPH_OK_BUTTON}}", 
		            handler: this._validate,
		            scope: this
		        }, {
		            text: "{{i18n PLUGINS_CORE_UI_WIDGET_HELPER_CHOOSEGLYPH_CANCEL_BUTTON}}",
		            handler: this._cancel,
		            scope: this
		        }]       
			});
			this._initialized = true;
		}
	},
	
	/**
	 * @private
	 * Create a filter for glyph
	 * @return {Ext.form.field.Text} the glyph filter field
	 */
	_createFilterField: function()
	{
		return Ext.create('Ext.form.field.Text', {
            cls: 'ametys',
            width: '100%',
            hideLabel: true,
            emptyText: "{{i18n PLUGINS_CORE_UI_WIDGET_HELPER_CHOOSEGLYPH_DIALOG_SEARCH}}",
            listeners: {change: Ext.Function.createBuffered(this._searchFilter, 500, this)}
        });
	},
	
	/**
	 * @private
	 * This listener is called on 'keyup' event on filter input field.
	 * Filters the glyphs on store.
	 * @param {Ext.form.Field} field The field
	 */
	_searchFilter: function (field) 
	{
		var value = new String(field.getValue()).trim();
		this._dataView.getStore().filter('cssClassNamesAsString', new RegExp(value));
	},
	
	/**
	 * @private
	 * Create the data view for glyph
	 * @return {Ext.view.View} the glyph data view
	 */
	_createDataView: function()
	{
		var dataView = Ext.create ('Ext.view.View',
		{
			itemSelector: 'div.data-view-glyph-icon',
			cls: "data-view-glyph-icons",
            border: false,
			overItemCls: 'x-view-over',
			selectedItemCls: 'x-view-over',
            scrollable: true,
            flex: 1,
			
            tpl: new Ext.XTemplate(
				'<tpl for=".">',
					'<div class="data-view-glyph-icon">',
						'<div class="glyph-icon-class {[values.cssClassNames[0]]}" title="{[values.cssClassNames.join(\'\\n\')]}"></div>',
					'</div>',
				'</tpl>'
			)
		});
		
		return dataView;
	},
	
	/**
	 * @private
	 * Initialize the dialog
     * @param {Object} storeCfg The store configuration
	 */
	_initDialog: function(storeCfg)
	{
        if (!storeCfg)
        {
            this.getLogger().error('Missing store configuration #storeCfg is missing. Unable to load available glyphs.');
            return;
        }
        
        var store = Ext.create('Ext.data.Store', Ext.applyIf(storeCfg, {
            autoDestroy: true,
            model: 'Ametys.helper.ChooseGlyph.Model'
        }));
                   
        this._dataView.setStore(store);
		this._dataView.getStore().load();
		this._filterField.setValue("");
		store.clearFilter();
		store.filter('cssClassNamesAsString', "");
	},
	
	/**
	 * @private
	 * Function invoked when clicking the 'ok' button, saving the selected glyph
	 */
	_validate: function ()
	{
		if (Ext.isFunction(this._cbFn))
		{
			var glyphNodes = this._dataView.getSelectedNodes();
			if (glyphNodes && glyphNodes.length > 0)
			{
				var glyph = this._dataView.getRecord(glyphNodes[0]);
				this._cbFn (glyph.get('cssClassNames')[0]);
			}
			else
			{
				this._cbFn (null);
			}
		}
		
		this._box.hide();
	},
	
	/**
	 * @private
	 * Fonction invoked when clicking the 'cancel' button
	 */
	_cancel: function()
	{
		this._cbFn (null);
		this._box.hide();
	}
});

/**
 * @private
 * The model used in the {@link Ametys.helper.ChooseGlyph} store 
 */
Ext.define('Ametys.helper.ChooseGlyph.Model', {
    extend: 'Ext.data.Model',
    fields: [
        { name:'cssClassNames' },
        { name:'cssClassNamesAsString', mapping: 'cssClassNames', compute: function(v) { return v.join(" "); } }
    ]
});