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

/**
 * Singleton handling workflow actions on form entries
 */
Ext.define('Ametys.plugins.forms.workflow.AbstractFormEntriesWorkflowAction', {
	
	/**
	 * @private
	 * @property {Number} _count Counter for processed entries
	 */
	_count: 0,
	
	/**
	 * @private
	 * @property {String[]} _cumulatedEntryIds Array of processed entry ids
	 */
	_cumulatedEntryIds: [],
	
	/**
	 * @private
	 * @property {Ametys.window.DialogBox} _commentBox The pop-up window embedding a simple form with textarea to allow the user to enter a comment on workflow action
	 */
	_commentBox: null,
	
	/**
     * @protected
     * Get the form target type
     */
	getFormTargetType: function()
	{
        // To implement
        return null;
    },
    
    /**
     * @protected
     * Get the url to do workflow action
     * @param {String} actionId the action id
     */
    getActionUrl : function(actionId)
    {
        // To implement
        return null;
    },
	
	/**
     * @protected
     * Get role of the mail helper
     */
    getMailHelperRole : function()
    {
        // To implement
        return null;
    },
	
	/**
     * @protected
     * Get form entry target type
     */
    getFormEntryTargetType : function()
    {
        // To implement
        return null;
    },
    
	/**
	 * Action function to be called by the controller.
	 * Will execute the workflow action of controller on all contents stored by the controller in controller.contents properties
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The clicked button's controller
	 */
	doAction: function (controller)
	{
		if (controller.getInitialConfig('comment') == "true")
		{
			this._showCommentBox (controller);
		}
		else
		{
			this._startAction (controller);
		}
	},
	
	/**
	 * @private
	 * Trigger the workflow action
	 * @param controller the clicked button's controller
	 * @param comment the comment
	 */
	_startAction: function(controller, comment)
	{
		var message = Ametys.message.MessageBus.getCurrentSelectionMessage();
		var formTarget = message.getTarget(this.getFormTargetType());
		if (!Ext.Object.isEmpty(formTarget))
    	{
	    	var formId = formTarget.getParameters().id;
	    	if (controller['send-mail'] === 'true')
	    	{
	    		// Show the send mail dialog box to the user 
	    		Ametys.plugins.forms.workflow.SendMailDialog.create(formId, controller, comment, this.getMailHelperRole(), Ext.bind(this._doStartAction, this));
	    	}
	    	else
	    	{
	    		this._doStartAction(formId, controller, comment);
	    	}
    	}
	},
	
	/**
	 * @private
	 * Execute the workflow action of the controller on all contents stored by the controller in controller.contents properties
	 * @param {String} formId the id of the form
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling the #doAction function
	 * @param {String} comment The comments written by the caller. Can be empty
	 * @param {String} sendMailInfoJSON the JSON strong containing the needed information to send mails 
	 */
	_doStartAction: function (formId, controller, comment, sendMailInfoJSON)
	{
		var actionId = controller.getInitialConfig('workflow-action-id');
		var entries = controller.entries;
		
		Ametys.data.ServerComm.suspend();
		
		Ext.Array.each(entries, function(entryId) {
			Ametys.data.ServerComm.send({
				plugin: 'forms',
				url: this.getActionUrl(actionId),
				parameters: {entryId: entryId, formId: formId, comment: comment, sendMailInfo: sendMailInfoJSON}, 
				priority: Ametys.data.ServerComm.PRIORITY_MAJOR, 
				callback: {
					handler: this._workflowActionCallback,
					scope: this,
					arguments: {
						entryId: entryId,
						entryAmount: entries.length, 
						controller: controller, 
						formId: formId
					}
				}
			});
		}, this);

		Ametys.data.ServerComm.restart();
		
		var subtargets = [];
		var targetId = this.getFormEntryTargetType();
		Ext.Array.each (entries, function(entryId) {
			subtargets.push({
				id: targetId,
				parameters: { 
					id: entryId,
					form: formId
				}
			})
		});
		
		var targets = [];
		targets.push ({
			id: this.getFormTargetType(),
			parameters: {
				id: formId
			},
			subtargets: subtargets
		}); 
		
		Ext.create("Ametys.message.Message", {
			type: Ametys.message.Message.WORKFLOW_CHANGING,
			targets: targets
		});
	},
	
	/**
	 * @private
	 * Callback function called after #_startAction is processed.
	 * Fires Ametys.message.Message.WORKFLOW_CHANGED message for concerned contents
	 * @param {Object} response The XML response provided by the {@link Ametys.data.ServerComm}
	 * @param {Object} args The callback parameters passed to the {@link Ametys.data.ServerComm#send} method
	 * @param {String} args.entryId the id of the entry
	 * @param {Number} args.entryAmount the amount of processed form entries
	 * @param {Ametys.ribbon.element.ui.ButtonController} args.controller the button's controller
	 * @param {String} args.formId the id of the involved form
	 */
	_workflowActionCallback: function (response, args)
	{
		if (Ametys.data.ServerComm.handleBadResponse("{{i18n PLUGINS_FORMS_WORKFLOW_ERROR_DESC}}", response, "Ametys.plugins.forms.workflow.FormEntriesWorkflowAction.doAction"))
        {
            return;
        }
		
		var success = Ext.dom.Query.selectValue ('> ActionResult > success', response) == "true";
		
		var workflowErrors = Ext.dom.Query.select ('> ActionResult > workflowValidation > error', response);
		if (!success && workflowErrors.length > 0)
		{
			var errorMsg = "{{i18n PLUGINS_FORMS_WORKFLOW_ERROR_DESC}}";
			errorMsg += '<ul>';
			for (var i=0; i < workflowErrors.length; i++)
			{
				errorMsg += '<li>' + Ext.dom.Query.selectValue("", workflowErrors[i]) + '</li>';
			}
			errorMsg += '</ul>';
			
			Ametys.Msg.show({
				title: "{{i18n PLUGINS_FORMS_WORKFLOW_ERROR_TITLE}}",
				msg: errorMsg,
				buttons: Ext.Msg.OK,
				icon: Ext.Msg.ERROR
			});
			return;
		}
		
		this._cumulatedEntryIds = this._cumulatedEntryIds || [];
        this._count = this._count > 0 ? this._count : 0;
        
        this._cumulatedEntryIds.push(args.entryId);
        this._count++;
		
		var max = args.entryAmount;
		if (this._count == max)
		{
			var subtargets = [];
			var targetId = this.getFormEntryTargetType();
			Ext.Array.each (this._cumulatedEntryIds, function(entryId) {
				subtargets.push({
					id: targetId,
					parameters: { 
						id: entryId,
						form: args.formId
					}
				})
			});
			
			var targets = [];
			targets.push ({
				id: this.getFormTargetType(),
				parameters: {
					id: args.formId
				},
				subtargets: subtargets
			}); 
			
			Ext.create("Ametys.message.Message", {
				type: Ametys.message.Message.WORKFLOW_CHANGED,
				targets: targets
			});
			
			this._count = 0;
			this._cumulatedEntryIds = [];
		}
	},
	
	/**
	 * @private
	 * This function show dialog to enter comment on workflow action
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling the #doAction function
	 */
	_showCommentBox: function (controller)
	{
		if (this._commentBox == null)
		{
			this._commentBox = Ext.create('Ametys.window.DialogBox', {
				title: "{{i18n PLUGINS_FORMS_WORKFLOW_COMMENTS_DIALOG_TITLE}}",
				icon: Ametys.getPluginResourcesPrefix("forms") + "/img/edition/mailreceipt_16.png",
				
				width: 450,
				height: 250,
				scrollable: false,
				
				defaults: {
					cls: 'ametys',
					labelAlign: 'right',
					labelSeparator: '',
					labelWidth: 120
				},
				
				items: [{
							xtype: 'component',
							html: "{{i18n PLUGINS_FORMS_WORKFLOW_COMMENTS_DIALOG_MESSAGE}}",
							width: '100%'
						}, 
						{
							xtype: 'textareafield',
							label: "{{i18n PLUGINS_FORMS_WORKFLOW_COMMENTS_DIALOG_TEXTAREA}}",
							name: 'comment',
							id: 'workflow-comment',
							ametysDescription: "{{i18n PLUGINS_FORMS_WORKFLOW_COMMENTS_DIALOG_TEXTAREA_DESC}}",
							width: '100%',
							height: 140
						}
				],
				
				defaultFocus: 'comment',
				closeAction: 'hide',
				buttons : [{
					text :"{{i18n PLUGINS_FORMS_WORKFLOW_COMMENTS_DIALOG_OK}}",
					handler : Ext.bind(this._validateComment, this, [controller])
				}, {
					text :"{{i18n PLUGINS_FORMS_WORKFLOW_COMMENTS_DIALOG_CANCEL}}",
					handler: Ext.bind(function() {this._commentBox.hide();}, this) 
				}]
			});
		}
		else
		{
			this._commentBox.down('button').setHandler (Ext.bind(this._validateComment, this, [controller]));
		}
		
		this._commentBox.down('#workflow-comment').setValue('');
		this._commentBox.show();
	},
	
	/**
	 * @private
	 * Function handler called when the 'Ok' button of #_commentBox dialog box is pressed
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling the #doAction function
	 */
	_validateComment: function (controller)
	{
		var comment = this._commentBox.down('#workflow-comment').getValue();
		this._commentBox.hide();
		this._startAction (controller, comment);
	}
});