/*
 *  Copyright 2017 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 to select one or more hierarchical contents on a tree.
 * See {@link #open} method.
 * 
 *          Ametys.cms.uihelper.ChooseHierarchicalContent.open({
 *              leafContentType: 'my.hierarchical.reference.table.content.type',
 *              multiple: false,
 *              values: ["foo"],
 *              callback: function(contents) {console.log(contents);},
 *              scope: this
 *          });
 */
Ext.define('Ametys.cms.uihelper.ChooseHierarchicalContent', {
    singleton: true,
    
    /**
     * @readonly
	 * @property {String} TOP_ITEM_ALERT_DEFAULT_TITLE The default title of alert when a item of first level (with children) is selected
	 */
	TOP_ITEM_ALERT_DEFAULT_TITLE: "{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_TOP_ITEM_ALERT_TITLE}}",
	/**
     * @readonly
	 * @property {String} TOP_ITEM_ALERT_DEFAULT_TEXT The default text of alert when a item of first level (with children) is selected
	 */
	TOP_ITEM_ALERT_DEFAULT_TEXT: "{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_TOP_ITEM_ALERT_TEXT}}",
    
    /**
     * Configure and open the helper dialog box to select a reference table entry in its hierarchy.
     * @param {Object} config The configuration :
     * @param {String} config.leafContentType The id of the content type for the leaves of the tree. Mandatory
     * @param {String} [config.title] The title of the dialog box
     * @param {String} [config.iconCls=ametysicon-list6] The CSS class for icon of the dialog box
     * @param {String} [config.helpMessage] The help message to display on top of dialog box
     * @param {String} [config.activateTopItemAlert=false] 'true' to activate the alert when a item of first level (with children) is selected
     * @param {String} [config.topItemAlertTitle] The title of alert when a item of first level (with children) is selected
     * @param {String} [config.topItemAlertText] The text of alert when a item of first level (with children) is selected
     * @param {String} [config.multiple=false] 'true' to allow to select multiple contents
     * @param {String} [config.values] The list of the ids of th econtents to initially check
     * @param {String} [config.allowToggleAutoposting] Allow the autoposting
     * @param {String} [config.activeAutoposting] Activate the autoposting button
     * @param {String} config.callback The callback function to call after the 'OK' button was clicked. The callback function will receive the following parameters:
     * @param {String} config.callback.contents The ids of the selected contents in the tree
     * @param {Boolean} config.callback.autoposting 'true' if the autoposting button is activated
     * @param {String} config.scope The scope of the callback function
     */
    open: function(config)
    {
        config = config || {};

        config.activateTopItemAlert = config.activateTopItemAlert === true || config.activateTopItemAlert === "true";
        config.topItemAlertTitle = config.topItemAlertTitle || Ametys.cms.uihelper.ChooseHierarchicalContent.TOP_ITEM_ALERT_DEFAULT_TITLE;
        config.topItemAlertText = config.topItemAlertText || Ametys.cms.uihelper.ChooseHierarchicalContent.TOP_ITEM_ALERT_DEFAULT_TEXT;
        config.multiple = config.multiple === true || config.multiple === "true";
        config.viewName = config.viewName || 'main';
        
        Ametys.data.ServerComm.callMethod({
            role: "org.ametys.cms.content.referencetable.HierarchicalReferenceTablesHelper",
            methodName: "isHierarchicalSimpleTree",
            parameters: [config.leafContentType],
            callback: {
                handler: this._isHierarchicalSimpleTreeCb,
                scope: this,
                arguments: config
            },
            waitMessage: false
        });
    },
    
    /**
     * @private
     * Callback invoked after retrieving the type of tree
     * @param {Boolean} isSimpleTree true if the tree is composed by simple contents only
     * @param {Object} config The dialog box configuration
     */
    _isHierarchicalSimpleTreeCb: function (isSimpleTree, config)
    {
        var box = this._createBox(config, isSimpleTree);
        box.show();
        
        var tree = box.down('#tree'),
            rootNode = tree.getRootNode();
            
        tree.getStore().load({
            node : rootNode,
            callback : function()
            {
                tree.expandNode(rootNode);
            },
            scope : this
        });
    },
    
    /**
     * @private
     * Create the tree displayed in the dialog box
     * @param {Object} config The configuration
     */
    _createTree: function(config)
    {
    	return Ext.create('Ametys.plugins.cms.content.tree.HierarchicalReferenceTablesTree', {
            itemId: 'tree',
            rootVisible: false,
            rootCfg: {
                expanded: false,
                text: "",
                contenttypesIds: [config.leafContentType]
            },
            bodyStyle: {
            	borderTopWidth: 0
            },
            region: 'center',
            split: true,
            scrollable: true,
            referenceTableId: config.leafContentType,
            checkSelection: true,
            checkMode: config.multiple,
            values: config.values,
            allowToggleAutoposting: config.allowToggleAutoposting,
            activeAutoposting: config.activeAutoposting
        });
    },
    
    /**
     * @private
     * Create the dialog box in order to select an item
     * @param {Object} config The configuration
     * @param {Boolean} simpleTree true if the tree is composed by simple contents only
     */
    _createBox: function(config, simpleTree)
    {
        var tree = this._createTree(config);
        
    	var multiple = config.multiple,
    		callback = config.callback;

    	var items = [tree];
    	
    	if (!simpleTree)
    	{
    		var iframe = Ext.create("Ext.ux.IFrame", {itemId: 'iframe'}); 
    		items.push({
                            split: true,
                            region: 'east',
                        	xtype: 'container',
                            layout: 'card',
                            itemId: 'card',
                            activeItem: 1,
                            border: false,
                            flex: 2,
                            items: [
                            	iframe,
                                {
                                    xtype: 'component',
                                    padding: '5',
                                    html: config.helpMessage || ("{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_NO_SELECTION}}")
                                }
                            ]
    		});	
    	}
    	
    	var box = Ext.create('Ametys.window.DialogBox', {
            title: config.title || (multiple ? "{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_DEFAULT_TITLE_MULTIPLE}}" : "{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_DEFAULT_TITLE}}"),
            iconCls: config.iconCls || 'ametysicon-list6',
            width: simpleTree ? 400 : 800,
            
            items: {
                xtype: 'container',
                layout: {
                    type: 'vbox',
                    align : 'stretch',
                    pack  : 'start'
                },
                border: false,
                items: [{
                    xtype: 'component',
                    padding: '5',
                    html: config.helpMessage || (multiple ? "{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_HINT_MULTIPLE}}" : "{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_HINT}}")
                },
                {
                	xtype: 'panel',
                    layout: 'border',
                    split: true,
                    height: 500,
                    flex: 1,
                    border: true,
                    items: items
                }
                ]
            },
            
            closeAction: 'destroy',
            referenceHolder: true,
            defaultButton: 'validate',
            
            buttons : [{
                reference: 'validate',
                itemId: 'ok-btn',
                text: "{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_OKBUTTON}}"
            }, {
                itemId: 'cancel-btn',
                text: "{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_CANCELBUTTON}}",
                handler: function(button) {
                    button.up('[xtype=dialog]').close();
                }
            }]
        });
        
        box.down("button[itemId='ok-btn']").setHandler (Ext.bind(this._validate, this, [box, config]));
        
        if (!simpleTree)
        {
            tree.on('selectionChange', this._onSelectionChanged, this, {args: [box, config]});
        }
        
        return box;
    },
    
    /**
	 * This listener is called on the click event on an node is processed. 
     * @param {Ametys.window.DialogBox} box The current dialog box
     * @param {Object} config The initial configuration object
	 * @param {Ext.selection.Model} sm The selection model
	 * @param {Ext.data.Model[]} records The selected records
	 * @private
	 */
    _onSelectionChanged: function (box, config, sm, records)
	{	
    	var cardPanel = box.down('#card');
    	
    	if (records.length > 0)
    	{
    		if (!records[0].get('isSimple'))
    		{
    			this._updateContentDetails(box, config, records[0].get('contentId'));
    			cardPanel.setActiveItem(0);
    		}
    		else
    		{
    			// simple content selection
        		cardPanel.setActiveItem(1);
    		}
    	}
    	else
    	{
    		// empty selection
    		cardPanel.setActiveItem(1);
    		cardPanel.layout.getActiveItem().update(("{{i18n PLUGINS_CMS_HELPER_CHOOSEHIERARCHICALCONTENT_NO_SELECTION}}"))
    	}
	},
	
	/**
     * Retrieve the current tree values, and call the callback function from the initial configuration sent to #open
     * @param {Ametys.window.DialogBox} box The current dialog box
     * @param {Object} config the initial config
     * @private
     */
    _validate: function (box, config)
    {
    	if (Ext.isFunction(config.callback))
        {
            var tree = box.down("#tree");
            
            var selectedNodes = config.multiple ? tree.getChecked() : tree.getSelectionModel().getSelection();
            var autoposting = tree.isActiveAutoposting();
            
            var hasAtLeastOneTopItem = false;
                contentIds = [];
                
	        Ext.Array.each (selectedNodes, function (node) {
	            contentIds.push(node.get('contentId'));
                
                if (config.activateTopItemAlert)
                {
                    // Is it possible to be more specific on first level nodes?
                    if (node.getDepth() == 1 
	                    && (node.hasChildNodes() || !node.isLeaf()) 
	                    && node.findChildBy(function(child) {
	                            return child.get('checked') == true;
	                        }, this, true) == null)
	                {
	                    hasAtLeastOneTopItem = true;
	                }
                }
	        }, this);
        
            if (config.activateTopItemAlert && hasAtLeastOneTopItem)
            {
                // Display alert
                Ametys.Msg.confirm(
	                config.topItemAlertTitle,
	                config.topItemAlertText,
	                function (buttonId)
	                {
	                    if (buttonId == 'no')
	                    {
	                        config.callback.call(this, config.multiple ? contentIds : (contentIds.length > 0 ? contentIds[0] : null), autoposting);
                            box.close();
	                    }
	                },
	                this
	            );
            }
            else
            {
                config.callback.call(this, config.multiple ? contentIds : (contentIds.length > 0 ? contentIds[0] : null), autoposting);
                box.close();
            }
        } 
    },
    
	 /**
	 * Update the details panel for the given content
     * @param {Ametys.window.DialogBox} box The current dialog box
     * @param {Object} config The initial configuration object
	 * @param {String} contentId The id of content
	 * @private
	 */
	_updateContentDetails: function (box, config, contentId)
	{	
        var additionParams = "&viewName=" + config.viewName;
        
        // FIXME CMS-2316
        var appParameters = Ametys.getAppParameters();
        
        Ext.Object.each(appParameters, function(key, value) {
            additionParams += '&' + key + '=' + encodeURIComponent(value);
        });
        
		var detailsUri = Ametys.CONTEXT_PATH + "/_content.html?contentId=" + contentId + additionParams;
        
        var iframe = box.down('#iframe');
		iframe.load(detailsUri)
	}
	
});