/*
 *  Copyright 2011 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 to create a new content. 
 * @private
 */
Ext.define('Ametys.plugins.cms.content.actions.ContentTypeActions', {
	singleton: true,

	/**
	 * The default workflow action id
	 * @private
	 */
	_DEFAULT_WORKFLOW_ACTION_ID: 220,
	
	/**
	 * Action function to be called by the controller.
	 * Add or remove the selected content type on concerned content
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 * @param {boolean} state The next state of the Button, true means pressed
	 */
	setContentType: function (controller, state)
	{
		var btnConfig = controller.getInitialConfig();
		
		var parentController = Ametys.ribbon.RibbonManager.getUI(btnConfig.controllerParentId);
		var contentIds = parentController.getContentIds();
		
		if (parentController.getContentIds().length > 0)
		{
			var contentType = btnConfig['contentTypes'] || btnConfig['contentType'];
			var actionId = btnConfig['workflowActionId'] ? parseInt(btnConfig['workflowActionId']) : this._DEFAULT_WORKFLOW_ACTION_ID;
			var contentId = parentController.getContentIds()[0];
			
			if (state)
			{
				this.addContentType(contentId, contentType, actionId);
			}
			else
			{
				this.removeContentType(contentId, contentType, actionId);
			}
		}
	},
	
	/**
	 * Add a content type on concerned content
	 * @param {String} contentId The id of concerned content
	 * @param {String} contentType The content type to add
	 * @param {Number} actionId The workflow action id
	 */
	addContentType: function (contentId, contentType, actionId)
	{
		Ametys.data.ServerComm.callMethod({
			role: 'org.ametys.cms.content.ContentHelper',
			methodName: 'addContentType',
			parameters: [contentId, contentType, actionId],
			callback: {
				scope: this,
				handler: this._addContentTypeCb,
				arguments: {
					contentId: contentId
				},
				scope: this
			},
			errorMessage: {
				msg: "{{i18n CONTENT_ADD_CONTENT_TYPE_ERROR}}",
				category: 'Ametys.plugins.cms.content.actions.ContentActions'
			}
		});
	},
	
	/**
	 * Remove a content type on concerned content
	 * @param {String} contentId The id of concerned content
	 * @param {String} contentType The content type to remove
	 * @param {Number} actionId The workflow action id
	 */
	removeContentType: function (contentId, contentType, actionId)
	{
		Ametys.Msg.confirm("{{i18n CONTENT_REMOVE_CONTENT_TYPE_CONFIRM_TITLE}}", 
				"{{i18n CONTENT_REMOVE_CONTENT_TYPE_CONFIRM}}",
				Ext.bind(this._confirmRemoveContentType, this, [contentType, contentId, actionId], 1)
		);
	},
	
	/**
	 * Callback function invoked after the #removeContentType confirm box is closed
	 * @param {String} answer Id of the button that was clicked
	 * @param {String} contentType The content type to remove
	 * @param {String} contentId The id of concerned content
	 * @param {Number} actionId The workflow action id
	 * @private
	 */
	_confirmRemoveContentType: function (answer, contentType, contentId, actionId)
	{
		if (answer == 'yes')
		{
			Ametys.data.ServerComm.callMethod({
				role: 'org.ametys.cms.content.ContentHelper',
				methodName: 'removeContentType',
				parameters: [contentId, contentType, actionId],
				callback: {
					scope: this,
					handler: this._removeContentTypeCb,
					arguments: {
						contentId: contentId
					},
					scope: this
				},
				errorMessage: {
					msg: "{{i18n CONTENT_REMOVE_CONTENT_TYPE_ERROR}}",
					category: 'Ametys.plugins.cms.content.actions.ContentActions'
				}
			});
		}
	},
	
	/**
	 * @private
	 * Callback function called after adding a content type
	 * @param {Object} result The server response
	 * @param {Object} params The callback arguments.
	 */
	_addContentTypeCb: function (result, params)
	{
		if (result.failure)
		{
			var errorMsg = "";
			
			var msg = result.msg;
			if (msg == 'non-modifiable-content')
			{
				errorMsg = "{{i18n CONTENT_ADD_CONTENT_TYPE_ERROR_NON_MODIFIABLE_CONTENT}}";
			}
			else if (msg == 'no-content-type')
			{
				errorMsg = "{{i18n CONTENT_ADD_CONTENT_TYPE_ERROR_NO_CONTENT_TYPE}}";
			}
			else if (msg == 'invalid-content-type')
			{
				errorMsg = "{{i18n CONTENT_ADD_CONTENT_TYPE_ERROR_INVALID_CONTENT_TYPE}}";
			}
			else
			{
				errorMsg = "{{i18n CONTENT_ADD_CONTENT_TYPE_ERROR}}";
			}
			
			Ametys.Msg.show({
				title: "{{i18n CONTENT_ADD_CONTENT_TYPE_ERROR_TITLE}}",
				msg: errorMsg,
				buttons: Ext.Msg.OK,
				icon: Ext.Msg.ERROR
			});
		}	
		
		if (result.success)
		{
			Ametys.cms.content.ContentDAO.getContent(params.contentId, Ext.bind(this._fireMessages, this));
		}
	},
	
	/**
	 * @private
	 * Callback function called after removing a content type
	 * @param {HTMLElement} result The XML document.
	 * @param {Array} params The callback arguments.
	 */
	_removeContentTypeCb: function (result, params)
	{
		if (result.failure)
		{
			var errorMsg = "";
			
			var msg = result.msg;
			if (msg == 'non-modifiable-content')
			{
				errorMsg = "{{i18n CONTENT_REMOVE_CONTENT_TYPE_ERROR_NON_MODIFIABLE_CONTENT}}";
			}
			else if (msg == 'empty-list')
			{
				errorMsg = "{{i18n CONTENT_REMOVE_CONTENT_TYPE_ERROR_EMPTY_LIST}}";
			}
			else
			{
				errorMsg = "{{i18n CONTENT_REMOVE_CONTENT_TYPE_ERROR}}";
			}
			
			Ametys.Msg.show({
				title: "{{i18n CONTENT_REMOVE_CONTENT_TYPE_ERROR_TITLE}}",
				msg: errorMsg,
				buttons: Ext.Msg.OK,
				icon: Ext.Msg.ERROR
			});
		}	
		
		if (result.success)
		{
			Ametys.cms.content.ContentDAO.getContent(params.contentId, Ext.bind(this._fireMessages, this));
		}
	},
	
	/**
	 * Action function to be called by the controller.
	 * Add or remove the selected mixin on concerned content
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 * @param {boolean} state The next state of the Button, true means pressed
	 */
	setMixinType: function (controller, state)
	{
		var btnConfig = controller.getInitialConfig();
		
		var parentController = Ametys.ribbon.RibbonManager.getUI(btnConfig.controllerParentId);
		var contentIds = parentController.getContentIds();
		
		if (parentController.getContentIds().length > 0)
		{
			var mixin = btnConfig['contentTypes'] || btnConfig['contentType'];
			var actionId = btnConfig['workflowActionId'] ? parseInt(btnConfig['workflowActionId']) : this.self._DEFAULT_WORKFLOW_ACTION_ID;
			var contentId = parentController.getContentIds()[0];
			
			if (state)
			{
				this.addMixinType(contentId, mixin, actionId);
			}
			else
			{
				this.removeMixinType(contentId, mixin, actionId);
			}
		}
	},
	
	/**
	 * Add a mixin on concerned content
	 * @param {String} contentId The id of concerned content
	 * @param {String} mixin The mixin to add
	 * @param {Number} actionId The workflow action id
	 */
	addMixinType: function (contentId, mixin, actionId)
	{
		Ametys.data.ServerComm.callMethod({
			role: 'org.ametys.cms.content.ContentHelper',
			methodName: 'addMixinType',
			parameters: [contentId, mixin, actionId],
			callback: {
				scope: this,
				handler: this._addMixinTypeCb,
				arguments: {
					contentId: contentId
				},
				scope: this
			},
			errorMessage: {
				msg: "{{i18n CONTENT_ADD_MIXIN_ERROR}}",
				category: 'Ametys.plugins.cms.content.actions.ContentActions'
			}
		});
	},
	
	/**
	 * Remove a mixin on concerned content
	 * @param {String} contentId The id of concerned content
	 * @param {String} mixin The mixin to remove
	 * @param {Number} actionId The workflow action id
	 */
	removeMixinType: function (contentId, mixin, actionId)
	{
		Ametys.Msg.confirm("{{i18n CONTENT_REMOVE_MIXIN_CONFIRM_TITLE}}", 
				"{{i18n CONTENT_REMOVE_MIXIN_CONFIRM}}",
				Ext.bind(this._confirmRemoveMixin, this, [mixin, contentId, actionId], 1)
		);
	},
	
	/**
	 * Callback function invoked after the #removeMixin confirm box is closed
	 * @param {String} answer Id of the button that was clicked
	 * @param {String} mixin The mixin to remove
	 * @param {String} contentId The id of concerned content
	 * @param {Number} actionId The workflow action id
	 * @private
	 */
	_confirmRemoveMixin: function (answer, mixin, contentId, actionId)
	{
		if (answer == 'yes')
		{
			Ametys.data.ServerComm.callMethod({
				role: 'org.ametys.cms.content.ContentHelper',
				methodName: 'removeMixinType',
				parameters: [contentId, mixin, actionId],
				callback: {
					scope: this,
					handler: this._removeMixinTypeCb,
					arguments: {
						contentId: contentId
					},
					scope: this
				},
				errorMessage: {
					msg: "{{i18n CONTENT_REMOVE_MIXIN_ERROR}}",
					category: 'Ametys.plugins.cms.content.actions.ContentActions'
				}
			});
		}
	},
	
	/**
	 * @private
	 * Callback function called after adding a content type
	 * @param {HTMLElement} result The JSON server response
	 * @param {Array} params The callback arguments.
	 */
	_addMixinTypeCb: function (result, params)
	{
		if (result.failure)
		{
			var errorMsg = "";
			
			var msg = result.msg;
			if (msg == 'non-modifiable-content')
			{
				errorMsg = "{{i18n CONTENT_ADD_MIXIN_ERROR_NON_MODIFIABLE_CONTENT}}";
			}
			else if (msg == 'no-mixin')
			{
				errorMsg = "{{i18n CONTENT_ADD_MIXIN_ERROR_NO_MIXIN}}";
			}
			else if (msg == 'invalid-mixin')
			{
				errorMsg = "{{i18n CONTENT_ADD_MIXIN_ERROR_INVALID_MIXIN}}";
			}
			else
			{
				errorMsg = "{{i18n CONTENT_ADD_MIXIN_ERROR}}";
			}
			
			Ametys.Msg.show({
				title: "{{i18n CONTENT_ADD_MIXIN_ERROR_TITLE}}",
				msg: errorMsg,
				buttons: Ext.Msg.OK,
				icon: Ext.Msg.ERROR
			});
		}	
		
		if (result.success)
		{
			Ametys.cms.content.ContentDAO.getContent(params.contentId, Ext.bind(this._fireMessages, this));
		}
	},
	
	/**
	 * @private
	 * Callback function called after removing a content type
	 * @param {HTMLElement} result The JSON server response
	 * @param {Array} params The callback arguments.
	 */
	_removeMixinTypeCb: function (result, params)
	{
		if (result.failure)
		{
			var errorMsg = "";
			
			var msg = result.msg;
			if (msg == 'non-modifiable-content')
			{
				errorMsg = "{{i18n CONTENT_REMOVE_MIXIN_ERROR_NON_MODIFIABLE_CONTENT}}";
			}
			else
			{
				errorMsg = "{{i18n CONTENT_REMOVE_MIXIN_ERROR}}";
			}
			
			Ametys.Msg.show({
				title: "{{i18n CONTENT_REMOVE_MIXIN_ERROR_TITLE}}",
				msg: errorMsg,
				buttons: Ext.Msg.OK,
				icon: Ext.Msg.ERROR
			});
		}	
		
		if (result.success)
		{
			Ametys.cms.content.ContentDAO.getContent(params.contentId, Ext.bind(this._fireMessages, this));
		}
	},
	
	/**
	 * Fire {@link Ametys.message.Message#MODIFIED} and {@link Ametys.message.Message#WORKFLOW_CHANGED} on content
	 * @param {Ametys.cms.content.Content} content The concerned content
	 * @private
	 */
	_fireMessages: function (content)
	{
		Ext.create("Ametys.message.Message", {
			type: Ametys.message.Message.MODIFIED,
			
			targets: {
				id: Ametys.message.MessageTarget.CONTENT,
				parameters: { contents: [content] }
			}
		});
		
		Ext.create("Ametys.message.Message", {
			type: Ametys.message.Message.WORKFLOW_CHANGED,
			
			targets: {
				id: Ametys.message.MessageTarget.CONTENT,
				parameters: { contents: [content] }
			}
		});
	}
	
	
});