/*
 *  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 tree panel for newsletters
 * @private
 */
 Ext.define('Ametys.plugins.newsletter.NewslettersTree', {
 	extend: 'Ext.tree.Panel',
 	
 	/**
 	 * @cfg {String} langContext The language code (defaults to null for all languages, a combobox will thus be drawn for choosing it).
 	 */
 	
 	/**
 	 * @cfg {boolean} categoriesOnly To display only categories. Defaults to 'false'.
 	 */

    /**
     * @cfg {Boolean} checkMode To select tags by checkboxes. Defaults to 'false'.
     */
    checkMode : false,

    /**
     * @cfg {String[]} values List of checkboxes name to check, if checkMode=true.
     */
    values : [],
    
 	/**
	 * @private
	 * @property {String} _lang The language code. Null if there is a combobox on top of the tree.
	 */

    initComponent: function ()
    {
        this.on('load', this._onLoad, this);
        this.on('checkchange', this._onCheckChange, this);
        this.callParent(arguments);
    },

    /**
     * @private
     * Function after tree loading
     * @param {Ext.data.TreeStore} store The tree store
     * @param {Ext.data.TreeModel[]} records The records
     * @param {Boolean} successful True if the operation was successful.
     * @param {Ext.data.Operation} operation The operation that triggered this load.
     * @param {Ext.data.NodeInterface} node The loaded node
     */
    _onLoad: function (store, records, successful, operation, node)
    {
        this._setInfos(node);
        
        if (this.checkMode === true)
        {
            this._setCheckboxes(node);
        }
    }, 

    /**
     * Iterate through the node childs, and call #_setInfo
     * @param {Ext.data.Model} node The node to iterate
     * @private
     */
    _setInfos: function (node)
    {
        var childNodes = node.childNodes;
        for (var i=0; i < childNodes.length; i++)
        {
            this._setInfo (childNodes[i]);
            this._setInfos (childNodes[i]);
        }
    },

    /**
     * Initialize the node, by setting the tooltip and autoexpand the providers
     * @param {Ext.data.Model} node The node to initialize
     * @private
     */
    _setInfo: function (node)
    {
        // auto expand providers
        if (node.get('type') == 'newsletter-category-provider')
        {
            this.expandNode(node);
        }

        if (node.get("disabled") == true)
        {
            var cls = node.get('cls');
            cls += (cls ? ' ' : '') + 'disabled';
            node.set('cls', cls);
        }
    },
    
    /**
     * Iterate through the children nodes, and call #_setCheckbox
     * @param {Ext.data.Model} node The node to iterate
     * @private
     */
    _setCheckboxes: function (node)
    {
        var childNodes = node.childNodes;
        for (var i=0; i < childNodes.length; i++)
        {
            this._setCheckbox (childNodes[i]);
            this._setCheckboxes (childNodes[i]);
        }
    },


    /**
     * Put a checkbox on nodes that can be checked, with the corresponding state. Does not verify any rights. 
     * @param {Ext.data.Model} node The node 
     * @private
     */
    _setCheckbox: function (node)
    {
        if (node.get('type') !== 'newsletter-category-provider')
        {
            node.set('checked', Ext.Array.contains(this.values, node.get('id')));
        }
        else
        {
            node.set('checked', null);
        }
    },

    /**
     * Verify if a node can be checked. If it can, his value is updated
     * @param {Ext.data.Model} node The node which state was updated
     * @param {Boolean} checked The new node state
     * @private
     */
    _onCheckChange: function(node, checked) 
    {
        if (node.get('disabled') === true)
        {
            node.set('checked', !checked);
            return ;
        }
        if (checked === true && Ext.Array.contains(this.values, node.get('id')) === false)
        {
            this.values.push(node.get('id'));
        }
        else if (checked === false && Ext.Array.contains(this.values, node.get('id')) === true)
        {
            Ext.Array.remove(this.values, node.get('id'));
            if (this._checkFilter === true)
            {
                this._filterByCheckedNodes(null, true);
            }
        }
    },
    
 	constructor: function(config)
 	{
 		this._categoriesOnly = config.categoriesOnly || false;
 		
 		var store = Ext.create('Ext.data.TreeStore', {
			model: 'Ametys.plugins.newsletter.NewslettersTree.NewsletterNodeEntry',
			autoLoad: false,
			
			proxy: {
				type: 'ametys',
				plugin: 'newsletter',
				url: 'newsletters.json',
				reader: {
					type: 'json'
				},
				extraParams: {
					sitename: Ametys.getAppParameter('siteName'),
					categoriesOnly: this._categoriesOnly
				}
			},
			
			sorters: [
				{
					property: 'type', // do not mix nodes with different types
					direction: 'DESC'
				},
				{
					property: 'text',
					direction: 'ASC'
				}
			]
		});
		store.on('beforeload', this._onBeforeLoad, this);
		
		var root = {
			expanded: false,
			iconCls: 'a-tree-glyph ametysicon-categories',
			text: '{{i18n PLUGINS_NEWSLETTER_UITOOL_CATEGORIES_ROOT_NODE_LABEL}}',
			id: 'root',
			type: 'newsletter-category-provider',
			allowDrag: false,
			allowDrop: false
		};
			
 		Ext.apply(config, {
 			store: store,
 			
 			root: root,
 			rootVisible: true,
 			
 			scrollable: true,
 			animate: true
 		});
 		
 		if (config.langContext == null)
 		{
	 		// Add form to select language in a combobox
 			var langCombo = Ametys.cms.language.LanguageDAO.createComboBox({
 				itemId: 'languages-combo',
				fieldLabel: "{{i18n PLUGINS_NEWSLETTER_UITOOL_LANGUAGES_LABEL}}",
 				flex: 1,
 				
 				listeners: {
 		        	'change': Ext.bind(this._onChangeLang, this)
 		        }
 			});
		
	 		config.dockedItems = [{
				dock: 'top',
				xtype: 'toolbar',
				layout: {
			        type: 'hbox',
			        align: 'stretch'
			    },
			    border: false,
				defaults : {
					cls: 'ametys',
					labelWidth: 55,
					labelSeparator: ''
				},
				
				items: langCombo
			}]
 		}
 		else
 		{
 			this._lang = config.langContext;
 		}
 		
 		this.callParent(arguments);
        
        this.on('itemmouseenter', this._createQtip, this);
 	},
 	
 	/**
	 * Listens before loading categories. 
	 * The load action will be canceled if it returns false 
	 * @param {Ext.data.Store} store The store.
	 * @param {Ext.data.operation.Operation} operation The Ext.data.operation.Operation object that will be passed to the Proxy to load the Store.
	 * @param {Object} eOpts The options object passed to Ext.util.Observable.addListener.
	 * @return {Boolean} False if the load action will be canceled.
	 * @private
	 */
	_onBeforeLoad: function(store, operation, eOpts)
	{
		var lang = this.getLang();
		
		operation.setParams( Ext.apply(operation.getParams() || {}, {
            checkMode: this.checkMode,
			lang: lang
		}));
	},
	
	/**
	 * Listens when a lang is changed.
	 * @param {Ext.form.field.Field} field The field
	 * @param {Object} newValue The new value.
	 * @param {Object} oldValue The original value.
	 * @private
	 */
	_onChangeLang: function(field, newValue, oldValue)
	{
		this.getSelectionModel().select(this.getRootNode());
	    // Refresh the root node.
	    this.refreshNode();
	},
	
	/**
	 * Refreshes the given node
	 * @param {Ext.data.NodeInterface} [node] The node to refresh. Root node by default.
	 * @param {Function} [callback] The callback function to call when the refresh is over.
	 */
	refreshNode: function(node, callback)
	{
		node = node || this.getRootNode();
		if (!Ext.isFunction(callback))
		{
			callback = Ext.emptyFn;
		}
		
        this.getStore().load({
            node : node,
            callback : function()
            {
            	callback();
                Ext.defer(this.expandNode, 200, this, [ node, false, null ]);
            },
            scope : this
        });
	},
 	
 	/**
 	 * Gets the current lang.
 	 * @return {String} The lang.
 	 */
 	getLang: function()
 	{
 		if (this._lang)
 		{
 			return this._lang;
 		}
 		else
 		{
 			return this.down("combobox[itemId='languages-combo']").getValue();
 		}
 	},
    
    /**
     * @private
     * Destroy and create the node tooltip when the mouse enters the node
     * @param {Ext.view.View} view The tree view
     * @param {Ext.data.Model} node The tree node
     * @param {HTMLElement} el The node's element
     */
    _createQtip: function (view, node, el)
    {
        if (!node.isRoot())
        {
            Ext.QuickTips.unregister(el);
            Ext.QuickTips.register(Ext.apply({target: el, id: el.id + '-tooltip'}, this._getTooltip(node)));
        }
    },
    
    /**
     * Get the tooltip configuration
     * @param {Ext.data.Model} node The tree node
     * @returns {Object} The tooltip configuration. See Ametys.ui.fluent.Tooltip.
     * @private
     */
    _getTooltip: function(node)
    {
        return {
            title: node.get('text'),
            glyphIcon: node.get('tooltipIconCls'),
            imageWidth: 48,
            imageHeight: 48,
            text: node.get('description'),
            inribbon: false
        };
    },
 	
 });