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

/**
 * Cost modeling status action
 * @private
 */
Ext.define('Ametys.plugins.odf.pilotage.actions.CostModelingActions', {
	singleton: true,
	
	/**
 	 * @private
 	 * @property {Ametys.window.DialogBox} _box The dialog box for creating/editing a catalog.
 	 */
 	 
 	/**
 	 * @private
 	 * @property {Ext.form.Panel} _formPanel The form panel of the dialog box.
 	 */
 	
 	/**
	 * @private
	 * @property {Boolean} _initialized Indicates if the create/edit dialog box is initialized.
	 */
	
	/**
	 * @private
	 * @property {Boolean} _catalogStoreNeedsToBeRefreshed Indicates if the store of the fromCatalog field is outdated.
	 */
	
	/**
	 * Open the cost modeling tool
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	openTool: function(controller) {
		var target = controller.getMatchingTargets()[0];
		if (target && !Ext.Array.contains(target.getParameters().types, "org.ametys.plugins.odf.Content.orgunit"))
		{
		    Ametys.ribbon.element.ui.button.OpenToolButtonController._act(controller);
		}
		else
		{
			var languages = controller.getInitialConfig()["languages"];
			this._delayedInitialize(controller, languages);
	 		this._box.show();
	 		this._initForm();
		}
	},
	
    /**
     * Save overridden values by the user in the cost modeling tool
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    saveTool: function(controller) {
        var tool = Ametys.tool.ToolsManager.getFocusedTool();
        var message = "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_CONFIRM}}";
        
        var overriddenData = tool._getOverriddenData();
        var processedData = {};
        
        
        //Add course parts into processed map for message 
        for (var contentId in overriddenData)
        {
        	let currentNode = tool.getCurrentNode(contentId)
			
        	if (currentNode.length && tool.isCoursePart(currentNode[0]))
        	{
        		var parentNode = tool.getParentNode(currentNode[0]);
        		if (parentNode != null)
        		{
        			var parentId = parentNode.getData().contentId
        			if (!processedData[parentId])
        	        {
        	        	processedData[parentId] = {};
        	        	processedData[parentId]['title'] = parentNode.getData().title;
        	        }
        	        var courseParts = processedData[parentId]["courseParts"] || {};
        	        courseParts[contentId] = overriddenData[contentId];
        	        
        	        processedData[parentId]["courseParts"] = courseParts;
        		}
        	}
        }
        
        message += "<ul>";
        for (contentId in overriddenData)
        {
            let currentNode = tool.getCurrentNode(contentId);
        	if (currentNode.length && !tool.isCoursePart(currentNode[0]))
            {
	            message += this._createListIfDataDefined(overriddenData[contentId], processedData[contentId])
            }
        }
        
        // Case where edited coursePart's parent does not have change
        for(contentId in processedData)
        {
        	if (!overriddenData[contentId])
        	{
	            message += this._createListIfDataDefined({}, processedData[contentId])
        	}
        }
        message += "</ul>";
        
        Ametys.Msg.confirm(
            "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_LABEL}}", 
            message, 
            Ext.bind(this._saveToolConfirm, this, [controller, overriddenData], 1),
            this
        );
    },
    
	_createListIfDataDefined: function(contentData, processedData)
	{
		var message = "<li>";
        
        message += processedData ? processedData['title'] : contentData['title'];
        
        message += "<ul>";
        message += this._createListItemIfDataDefined("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_EFFECTIVES}}", contentData, 'effectivesGlobal');
        message += this._createListItemIfDataDefined("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_GROUPS}}", contentData, 'groups');
        message += this._createListItemIfDataDefined("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_NB_HOURS}}", contentData, 'nbHours');
        
        //manage course parts
        if (processedData)
        {
        	for (var [coursePartId, value] of Object.entries(processedData["courseParts"])) {
                message += this._createListIfDataDefined(value);
        	}
        }
        message += "</ul>";
        
        message += "</li>";
        return message;
	},
	
    _createListItemIfDataDefined: function(prefix, data, dataName)
    {
        var message = "";
        var dataValue = data[dataName];
        if (dataValue)
        {
            message += "<li>";
            message += prefix;
            message += "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_SEPARATOR}}";
            message += dataValue;
            message += "</li>";
        }
        return message;
    },
    
     /**
     * @private
     * Callback after asking for a save 
     * @param {String} answer 'yes' to save
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    _saveToolConfirm: function (answer, controller, overriddenData)
    {
        if (answer == 'yes')
        {
            Ametys.data.ServerComm.callMethod({
                role: "org.ametys.plugins.odfpilotage.helper.CostComputationTreeHelper",
                methodName: "saveOverriddenData",
                parameters: [overriddenData],
                callback: {
                    handler: Ext.bind(this._resetAfterSave, this, [controller], 1),
                    scope: this,
                }
            });
        }
    },
    
	/**
	 * Refresh the cost modeling tool
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	refreshTool: function(controller) {
		var tool = Ametys.tool.ToolsManager.getFocusedTool();
		// If old data are already in the tree config, we dont need to call the server
		if (!tool._treePanel.config.oldData)
		{
			Ametys.data.ServerComm.callMethod({
				role: "org.ametys.plugins.odfpilotage.helper.CostComputationTreeHelper",
				methodName: "getOldData",
				parameters: [],
				callback: {
					handler: this._refreshToolCb,
					scope: this,
					arguments: tool
				}
			});
		}
		else
		{
			tool._customRefresh();
		}
	},
	
	/**
	 * Callback function called after #_refreshTool is processed.
	 * @param {Object} data a map containing he report gathered by the content id
	 * @param {Object} tool the focused tool
	 * @private
	 */
	_refreshToolCb: function(data, tool)
	{
		Ext.apply(tool._treePanel.config, {
		    oldData: data,
		    overriddenData: tool._getOverriddenData()
		});
		tool._customRefresh();
	},
    
    /**
     * Create the reset tool confirmation dialogue
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    reset: function(controller)
    {
        Ametys.Msg.confirm(
            "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_RESTART_LABEL}}", 
            "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_RESTART_CONFIRM}}", 
            Ext.bind(this._resetConfirm, this, [controller], 1),
            this
        );
    },
    
     /**
     * @private
     * Callback after asking for a restart 
     * @param {String} answer 'yes' to restart
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    _resetConfirm: function (answer, controller)
    {
        if (answer == 'yes')
        {
            this._resetTool();
        }
    },
    
     /**
     * @private
     * Callback after saving data
     * @param {Object} response The response given after trying to save overridden data
     * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    _resetAfterSave: function(response, controller)
    {
        if (response.unknown || response.workflow || response.invalidAction || response.attributeRight || response.error)
        {
            var msg = "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_HINT}}<br/><br/>";
            
            if (response.unknown)
            {
                msg += "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_UNKNOWN}}<br/><ul>";
                for (var json of response.unknown)
                {
                    msg += "<li>";
                    msg += Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_UNKNOWN_DETAIL}}", json.contentId);
                    msg += "</li>";
                }
                msg += "</ul>";
            }
            
            if (response.workflow)
            {
                msg += "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_WORKFLOW}}<br/><ul>";
                for (var json of response.workflow)
                {
                    msg += "<li>";
                    msg += Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_WORKFLOW_DETAIL}}", json.title, json.code);
                    msg += "</li>";
                }
                msg += "</ul>";
            }
            
            if (response.invalidAction)
            {
                msg += "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_INVALIDACTION}}<br/><ul>";
                for (var json of response.invalidAction)
                {
                    msg += "<li>";
                    msg += Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_INVALIDACTION_DETAIL}}", json.title, json.code);
                    msg += "</li>";
                }
                msg += "</ul>";
            }
            
            if (response.attributeRight)
            {
                msg += "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_RIGHTATTRIBUTE}}<br/><ul>";
                for (var json of response.attributeRight)
                {
                    msg += "<li>";
                    msg += Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_RIGHTATTRIBUTE_DETAIL}}", json.attributeLabel, json.attributePath, json.title, json.code);
                    msg += "</li>";
                }
                msg += "</ul>";
            }
            
            if (response.error)
            {
                msg += "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_ERROR}}<br/><ul>";
                for (var json of response.error)
                {
                    msg += "<li>";
                    msg += Ext.String.format("{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_ERROR_DETAIL}}", json.title, json.code);
                    msg += "</li>";
                }
                msg += "</ul>";
            }
            
            msg += "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_LOG_DETAILS}}<br/>";
            msg += "<b>{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_ASK_REFRESH}}</b>";
            
            Ametys.Msg.show({
                title: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_SAVE_ERROR_TITLE}}", 
                message: msg,
                buttons: Ext.Msg.YESNO,
                icon: Ext.Msg.WARNING,
                fn: Ext.bind(this._resetConfirm, this, [controller], 1),
                scope: this
            });
        }
        else
        {
            this._resetTool();
        }
    },
    
    /**
	 * Reset the cost modeling tool
	 */
	_resetTool: function()
	{
        var tool = Ametys.tool.ToolsManager.getFocusedTool();
		tool._overriddenData = {};
		Ext.apply(tool._treePanel.config, {
		    oldData: null,
		    overriddenData: {}
		});
		tool.refresh();
		tool.setDirty(false);
		tool._treePanel.getDockedComponent("costModelingHint").setVisible(false);
	},
	
	/**
	 * @private
	 * Creates the dialog box
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 * @param languages A map containing available languages
	 */
	_delayedInitialize: function (controller, languages)
	{
		if (!this._initialized)
		{
			this._formPanel = this._createFormPanel(languages);
			
			this._box = Ext.create('Ametys.window.DialogBox', {
				title: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_CONTEXT_CHOICE}}",
	            icon: Ametys.getPluginResourcesPrefix('odf') + '/img/catalog/catalog_16.png',
	            
	            width: 450,
		        scrollable: false,
	            
	            items: [ this._formPanel ],
	            
	            defaultFocus: 'title',
	            closeAction: 'hide',
	            buttons: [{
	                text: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_CONTEXT_CHOICE_OK_BUTTON}}",
	                handler: Ext.bind(this._validate, this, [controller])
	            }, {
	                text: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_CONTEXT_CHOICE_CANCEL_BUTTON}}",
	                handler: Ext.bind( function() {this._box.close();}, this)
	            }]    
			});
			
			this._initialized = true;
		}
	},
	
	/**
 	 * Creates the form panel of this dialog box.
 	 * @param languages Map containing all available languages
 	 * @return {Ext.form.Panel} The form panel
 	 * @private
 	 */
 	_createFormPanel: function(languages)
 	{
 		var data = [];
		for (var i in languages)
		{
			data.push([i, languages[i]]);
		}
		
		var formPanel = Ext.create('Ext.form.Panel', {
	        defaultType: 'combo',
	        defaults: {
	        	cls: 'ametys',
	        	labelSeparator: '',
	        	labelAlign: 'right',
	        	labelWidth: 80,
	        	width: '100%',
	        	msgTarget: 'side'
	        },
	        
	        border: false,
	        scrollable: false,
	        
	        items: [
		        {
		        	xtype: 'container',
		        	itemId: 'hint',
		        	html: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_CONTEXT_CHOICE_HINT}}",
		        	cls: 'a-text'
		        },
		        Ametys.odf.catalog.CatalogDAO.createComboBox({
		            name: 'catalog',
		            itemId: 'catalog',
		            allowBlank: false
		        }),
                {
                    xtype: 'combobox',
                    name: 'lang',
                    itemId: 'lang',
                    value: Ametys.cms.language.LanguageDAO.getCurrentLanguage(),
                    fieldLabel: "{{i18n plugin.odf-pilotage:PLUGINS_ODF_PILOTAGE_TOOL_COST_MODELING_CONTEXT_CHOICE_LANG}}",
                    forceSelection: true,
                    allowBlank: false,
	                valueField: 'value',
	                displayField: 'label',
	                queryMode: 'local',
	                store: {
	                    type: 'array', // Ext.data.ArrayStore
	                    fields: ['value', 'label'],
	                    data: data
	                }
                }
	        ]
        	
 		});
 		
 		return formPanel;
 	},
	
	/**
 	 * @private
 	 * Initializes the form with some optional values.
 	 */
	_initForm: function ()
 	{
 		var form = this._formPanel.getForm();
		form.reset();
        
        Ametys.odf.catalog.CatalogDAO.getDefaultCatalogName([], function(catalogName) {
            form.findField('catalog').setValue(catalogName)
        }, this);
        Ametys.cms.language.LanguageDAO.getCurrentLanguage([], function(lang) {
            form.findField('lang').setValue(lang)
        }, this);
 	},
 	
 	/**
 	 * @private
 	 * Handler for the 'ok' button of the dialog box
 	 */ 
    _validate: function (controller)
    {
        var form = this._formPanel.getForm();
        if (!form.isValid())
        {
        	return;
        }
        
        var values = form.getValues();
 		
        var parameters = Ext.apply(controller.config["opentool-params"], {catalog: values.catalog, lang: values.lang});
        controller.config["opentool-params"] = parameters;
        Ametys.ribbon.element.ui.button.OpenToolButtonController._act(controller);
       
        this._box.close();
    }
	
});