/*
 *  Copyright 2014 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 class defining the actions on comments
 * @private
 */
Ext.define('Ametys.plugins.cms.comment.CommentActions', {
	singleton: true,
	
	/**
	 * Action to edit a comment
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	edit: function (controller)
	{
		var commentTarget = controller.getMatchingTargets()[0];
		
		if (commentTarget != null)
		{
			this._delayedInitialized(controller);
			this._box.show();
			this._initForm (commentTarget, controller);
		}
	},
	
	/**
	 * @private
	 * Creates the dialog box
 	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	_delayedInitialized: function (controller)
	{
		if (this._initialized)
		{
			return;
		}
		
		this._form = Ext.create('Ext.form.Panel', {
			border: false,
			defaults: {
				cls: 'ametys',
				width: 360,
				xtype: 'textfield',
				msgTarget: 'side',
				labelSeparator: '',
				labelAlign: 'right'
			},
			
			items : [{
						name: 'contentId',
						xtype: 'hidden'
					 },
					 {
						name: 'commentId',
						xtype: 'hidden'
					 },
			         {
						itemId: 'author-name',
						name: 'author-name',
						fieldLabel: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_AUTHORNAME}}",
						ametysDescription: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_AUTHORNAME_DESC}}",
						allowBlank: false
					 },
					 {
						name: 'author-email',
						fieldLabel: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_AUTHOREMAIL}}",
						ametysDescription: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_AUTHOREMAIL_DESC}}",
						regex: /^([a-z0-9._-]+@[a-z0-9.-]{2,}[.][a-z]{2,3})?$/
					 },
					 {
						 xtype: 'checkboxfield',
						 name: 'author-emailhidden',
						 inputValue: true,
						 uncheckedValue: false,
						 fieldLabel: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_AUTHOREMAILHIDDEN}}",
						 ametysDescription: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_AUTHOREMAILHIDDEN_DESC}}"
					 },
					 {
							name: 'author-url',
							fieldLabel: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_AUTHORHOMEPAGE}}",
							ametysDescription: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_AUTHORHOMEPAGE_DESC}}",
							regex: /^(https?:\/\/.+)?$/
					 },
					 {
						 	xtype: 'textarea',
							name: 'text',
							fieldLabel: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_CONTENT}}",
							ametysDescription: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_CONTENT_DESC}}",
							height: 100,
							allowBlank: false
					 }
			]
		});
		
		this._box = Ext.create('Ametys.window.DialogBox', {
			title :"{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_CAPTION}}",
			icon : Ametys.getPluginResourcesPrefix('cms') + "/img/content/comments/edit_comment_16.png",
			
			width: 420,
			scrollable: true,
			layout: "fit",
			
			items: [ this._form ],
			
			defaultFocus: 'author-name',
			closeAction: 'hide',
			
			referenceHolder: true,
			defaultButton: 'validate',
			
			buttons : [{
				reference: 'validate',
				text :"{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_OK}}",
				handler : Ext.bind (this._save, this, [controller]),
				scope: this
			}, {
				text :"{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_CANCEL}}",
				handler : function () { this._box.close()},
				scope: this
			} ]
		});
		
		this._initialized = true;
	},
	
	
	/**
	 * Init the form
	 * @param {Ametys.message.MessageTarget} commentTarget The comment target to edit
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	_initForm: function (commentTarget, controller)
	{
		this._mask = Ext.create('Ext.LoadMask', {
			target: this._box,
			msg: "{{i18n plugin.core-ui:PLUGINS_CORE_UI_LOADMASK_DEFAULT_MESSAGE}}"
		});
		
		this._mask.show();

		controller.serverCall('getComment', [commentTarget.getParameters().content, commentTarget.getParameters().id], Ext.bind(this._initFormCb, this), 
						{
							errorMessage: {
									msg: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_ERROROPEN}}",
									category: 'Ametys.plugins.cms.comment.CommentActions.edit'
							}
						});
	},
	
	/**
	 * @private
	 * Callback function called after #_initForm is processed
	 * Fills the edition form
	 * @param {Object[]} response the server's response
	 */
	_initFormCb: function (response)
	{
		if (response['comments'] == null)
		{
			return;
		}
		
		var comment = response['comments']['comment'];
		
		var form = this._form.getForm();
		
		form.findField('commentId').setValue(comment['id']);
		form.findField('contentId').setValue(comment['content']['id']);
		form.findField('author-name').setValue(comment['author-name']);
		
		var email = comment['author-email'];
		form.findField('author-email').setValue(email != null ? email['value'] : '');
		form.findField('author-emailhidden').setValue(email != null ? email['hidden'] == 'true' : false);
		
		form.findField('author-url').setValue(comment['author-url']);
		form.findField('text').setValue(comment['text']);
		
		if (this._mask)
		{
			this._mask.hide();
			delete this._mask;
		}
	},
	
	/**
	 * @private
	 * Submit the form to save modifications
  	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	_save: function (controller)
	{
		var form = this._form.getForm();
		if (!form.isValid())
		{
			return;
		}
		
		var params = form.getValues();
		
		controller.serverCall('editComment', [params], Ext.bind(this._saveCb, this),
			   {
					errorMessage: {
								msg: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_EDIT_DIALOG_ERRORSAVE}}",
								category: 'Ametys.plugins.cms.comment.CommentActions.edit'
					}
		       });
	},
	
	/**
	 * Callback function after saving
	 * @param {Object[]} response the server's response in JSON.
	 */
	_saveCb: function (response)
	{
		Ext.create("Ametys.message.Message", {
			type: Ametys.message.Message.MODIFIED,
			targets: {
				id: Ametys.message.MessageTarget.COMMENT,
				parameters: { 
					id: response.id,
					content: response.contentId,
                    reportsCount: response.reportsCount
				}
			}
		});
		this._box.hide();
	},
	
	// ------------------------ REMOVE ------------------------------------//
	/**
	 * Action to delete comments
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	remove: function (controller)
	{
		var commentTargets = controller.getMatchingTargets();
		
		if (commentTargets.length > 0)
		{
			Ametys.Msg.confirm("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_DELETE_CONFIRM_TITLE}}", 
					"{{i18n PLUGINS_CMS_CONTENT_COMMENTS_DELETE_CONFIRM_DESCRIPTION}}", 
					Ext.bind(this._doRemove, this, [controller, commentTargets], 1),
					this
			);
		}
	},
	
	/**
	 * Callback function invoked after the #remove confirm box is closed
	 * @param {String} answer Id of the button that was clicked
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling the #act function
	 * @param {Ametys.message.MessageTarget[]} commentTargets The registered comments targets
	 * @private
	 */
	_doRemove: function (answer, controller, commentTargets)
	{
		if (answer == 'yes')
		{
			var contentIds = {};
			for (var i=0; i < commentTargets.length; i++)
			{
				var contentId = commentTargets[i].getParameters().content;
				if (!contentIds[contentId])
				{
					contentIds[contentId] = [];
				}
				contentIds[contentId].push(commentTargets[i].getParameters().id);
			}
			
			controller.serverCall('deleteComments', [contentIds], Ext.bind(this._removeCb, this),
				   {
						errorMessage: {
							msg: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_DELETE_UNKNOWN_ERROR}}",
							category: 'Ametys.plugins.cms.comment.CommentActions.remove'
						}
					});
		}
	},
	
	/**
	 * @private
	 * Callback function called after removing comments
	 * @param {Object[]} response the server's response in JSON.
	 */
	_removeCb: function (response)
	{
		var errorMsg = '';
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNKNOWN_CONTENTS}}", response['unknown-contents'], 'contentId');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_NORIGHT_CONTENTS}}", response['noright-contents'], 'contentTitle');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNCOMMENTABLE_CONTENTS}}", response['uncommentable-contents'], 'contentTitle');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNKNOWN_COMMENTS}}", response['undeleted-comments'], 'contentTitle');
		
		if (errorMsg.length > 0)
		{
			Ametys.log.ErrorDialog.display({
				title: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_DELETE_ERRORS_TITLE}}",
				text: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_DELETE_ERRORS_DESC}}",
				details: errorMsg,
				category: 'Ametys.plugins.cms.comment.CommentActions.remove'
			});
		}
		
		var targets = [];
		
		var deletedComments = response['deleted-comments'];
		for (var i=0; i < deletedComments.length; i++)
		{
			targets.push({
				id: Ametys.message.MessageTarget.COMMENT,
				parameters: { 
					id: deletedComments[i].id,
					content: deletedComments[i].contentId,
                    reportsCount: 0
				}
			});
		}
		
		if (targets.length > 0)
		{
			Ext.create("Ametys.message.Message", {
				type: Ametys.message.Message.DELETED,
				targets: targets
			});
		}
	},
	
	/**
	 * @private
	 * Constructs the error message
	 * @param {String} intro The introduction text
	 * @param {Object[]} elmts The elements in error
	 * @param {String} name The attribute to display for elements in error
	 */
	_getErrorMsg: function (intro, elmts, name)
	{
		if (elmts.length > 0)
		{
			var elmt = [];
			for (var i=0; i < elmts.length; i++)
			{
				elmt.push(elmts[name])
			}	
			
			return intro + elmt.join(', ') + '<br/>';
		}
		return '';
	},
	
	// ----------------------------- VALIDATE ------------------------------------//
	
	/**
	 * Action to validate comments
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	validate: function (controller)
	{
		var comments = controller._matchingComments;
		
		var contentIds = {};
		for (var i=0; i < comments.length; i++)
		{
			var contentId = comments[i].content;
			if (!contentIds[contentId])
			{
				contentIds[contentId] = [];
			}
			contentIds[contentId].push(comments[i].id);
		}
		
		controller.serverCall('validateComments', [contentIds], Ext.bind(this._validateCb, this),  
				{
			    	errorMessage: {
			    		msg: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_VALIDATE_UNKNOWN_ERROR}}",
			    		category: 'Ametys.plugins.cms.comment.CommentActions.validate'
			    	}
				});
	},
	
	/**
	 * @private
	 * Callback function called after validating comments
	 * @param {Object[]} response The server's response in JSON.
	 */
	_validateCb: function (response)
	{
		var errorMsg = '';
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNKNOWN_CONTENTS}}", response['unknown-contents'], 'contentId');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_NORIGHT_CONTENTS}}", response['noright-contents'], 'contentTitle');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNCOMMENTABLE_CONTENTS}}", response['uncommentable-contents'], 'contentTitle');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNKNOWN_COMMENTS}}", response['error-comments'], 'contentTitle');
		
		if (errorMsg.length > 0)
		{
			Ametys.log.ErrorDialog.display({
				title: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_VALIDATE_ERRORS_TITLE}}",
				text: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_VALIDATE_ERRORS_DESC}}",
				details: errorMsg,
				category: 'Ametys.plugins.cms.comment.CommentActions.validate'
			});
		}
		
		var targets = [];
		
		var validatedComments = response['validated-comments'];
		for (var i=0; i < validatedComments.length; i++)
		{
			targets.push({
				id: Ametys.message.MessageTarget.COMMENT,
				parameters: { 
					id: validatedComments[i].id,
					content: validatedComments[i].contentId,
                    reportsCount: validatedComments[i].reportsCount
				}
			});
		}
		
		if (targets.length > 0)
		{
			Ext.create("Ametys.message.Message", {
				type: Ametys.message.Message.MODIFIED,
				targets: targets
			});
		}
	},
	
	// ----------------------------- INVALIDATE ------------------------------------//
	
	/**
	 * Action to invalidate comments
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	invalidate: function (controller)
	{
		var comments = controller._matchingComments;
		
		var contentIds = {};
		for (var i=0; i < comments.length; i++)
		{
			var contentId = comments[i].content;
			if (!contentIds[contentId])
			{
				contentIds[contentId] = [];
			}
			contentIds[contentId].push(comments[i].id);
		}
		
		controller.serverCall('invalidateComments', [contentIds], Ext.bind(this._invalidateCb, this), 
				{
			  		errorMessage: {
			  			msg: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_INVALIDATE_UNKNOWN_ERROR}}",
			  	  		category: 'Ametys.plugins.cms.comment.CommentActions.invalidate'
			  	  	}
				});
	},
	
	/**
	 * @private
	 * Callback function called after invalidating comments
	 * @param {Object[]} response The server's response in JSON.
	 */
	_invalidateCb: function (response)
	{
		var errorMsg = '';
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNKNOWN_CONTENTS}}", response['unknown-contents'], 'contentId');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_NORIGHT_CONTENTS}}", response['noright-contents'], 'contentTitle');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNCOMMENTABLE_CONTENTS}}", response['uncommentable-contents'], 'contentTitle');
		errorMsg += this._getErrorMsg("{{i18n PLUGINS_CMS_CONTENT_COMMENTS_ERROR_UNKNOWN_COMMENTS}}", response['error-comments'], 'contentTitle');
		
		if (errorMsg.length > 0)
		{
			Ametys.log.ErrorDialog.display({
				title: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_INVALIDATE_ERRORS_TITLE}}",
				text: "{{i18n PLUGINS_CMS_CONTENT_COMMENTS_INVALIDATE_ERRORS_DESC}}",
				details: errorMsg,
				category: 'Ametys.plugins.cms.comment.CommentActions.invalidate'
			});
		}
		
		var targets = [];
		
		var unvalidatedComments = response['unvalidated-comments'];
		for (var i=0; i < unvalidatedComments.length; i++)
		{
			targets.push({
				id: Ametys.message.MessageTarget.COMMENT,
				parameters: { 
					id: unvalidatedComments[i].id,
					content: unvalidatedComments[i].contentId,
                    reportsCount: unvalidatedComments[i].reportsCount
				}
			});
		}
		
		if (targets.length > 0)
		{
			Ext.create("Ametys.message.Message", {
				type: Ametys.message.Message.MODIFIED,
				targets: targets
			});
		}
	}
});