/*
 *  Copyright 2013 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 helper provides a dialog box to copy a content as a new content. 
 * The dialog box brings an advanced mode to allow to select the content attributes to copied in a tree.
 * See #open method.
 * @private
 */
Ext.define('Ametys.plugins.cms.content.helper.CopyContent', {
	singleton: true,
	
	/**
	 * @property {Ametys.window.DialogBox} _box The dialog box
	 * @private
	 */
	/**
	 * @property {Ametys.plugins.cms.content.tree.ViewTree} _tree The tree that displays the current view and allow the user to select/deselect the desired attributes.
	 * @private
	 */
	
	/**
	 * @property {String} _content The copied content.
	 * @private
	 */
	/**
	 * @property {Number} [_workflowInitActionId=111] The id of the workflow action to initialize the duplicated content. Can be null to use the default value.
	 * @private
	 */
	/**
	 * @property {Number} [_workflowEditActionId=2] The id of the workflow action to edit the target content. Can be null to use the default value.
	 * @private
	 */
	/**
	 * @property {String} [_viewName="default-edition"] The name of the view to be displayed in attributes tree. Can be null to use the default value.
	 * @private
	 */
     /**
     * @property {String} [_fallbackViewName="main"] The fallback view to be displayed in attributes tree. Used (for legacy purpose) when _viewName is not found.
     * @private
     */
	/**
	 * @property {String} [_viewMode="edition"] The mode of the view to be displayed in attributes tree Can be null to use the default value.
	 * @private
	 */
	/**
	 * @property {Function} _cbFn The callback function to be called after copy process
	 * @property {Object} _cbFn.report The copy report
	 * @private
	 */
	/**
	 * @property {Object} _scope The scope of the callback function. Can be null.
	 * @private
	 */
	
	 /**
     * @property {Boolean} [_checkByDefault=true] Indicates if the checkboxes should be checked or not.
     * @private
     */
    _checkByDefault: true,
    
	
	/**
	 * Open a dialog box to select content view in a tree in order to copy content as a new content
	 * @param {Object} config The configuration options. Has the following parameters:
	 * @param {Ametys.cms.content.Content} config.content (required) The content to copied
	 * @param {String} [config.icon] The full path to icon (16x16) for the dialog box
	 * @param {String} [config.title] The title of the dialog box.
	 * @param {String} [config.helpMsg1] The message displayed at the top of the dialog box.
	 * @param {String} [config.helpMsg2] The message displayed at the bottom of the dialog box.
	 * @param {Number} [config.workflowInitActionId=111] The workflow action id for copy content as a new content
	 * @param {Number} [config.workflowEditActionId=2] The workflow action id for editing the target content
	 * @param {String} [config.viewName="default-edition"] The view name
     * @param {String} [config.fallbackViewName="main"] The fallback view name to use if 'viewName' does not exist.
	 * @param {String} [config.viewMode="edition"] The view mode ('view' or 'edition')
	 * @param {Function} config.callback Callback function called after the dialog box is closed and the copy is processed.
	 * @param {Object} config.callback.report The copy report
	 * @param {Object} [config.scope] The callback scope.
	 */
	open: function(config)
	{
		if (!config.content)
		{
			Ametys.Msg.show({
				title: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENTVALUES_ERROR_TITLE}}",
				msg: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_NO_COPIED_CONTENT}}",
				buttons: Ext.Msg.OK,
				icon: Ext.Msg.ERROR
			});
			return;
		}
		
		this._cbFn = config.callback || Ext.emptyFn;
		this._scope = config.scope;
		
		this._content = config.content;
		this._viewName = config.viewName || 'default-edition';
        this._fallbackViewName = config.fallbackViewName || 'main';
		this._viewMode = config.viewMode || 'edition';
		this._workflowInitActionId = config.workflowInitActionId || 111;
		this._workflowEditActionId = config.workflowEditActionId || 2;
		if (config.checkByDefault != null)
        {
            this._checkByDefault = config.checkByDefault != "false"
        }
		// Check the user rights by retrieve the content type
        var me = this;
        var contentTypes = Ametys.cms.content.ContentTypeDAO.getContentTypes().createFiltered(function(contentType) {
            return me._content.getTypes().indexOf(contentType.getId()) != -1
                && contentType.hasRight()
                && !contentType.isMixin()
                && !contentType.isAbstract();
        });
        
        if (contentTypes.count() != this._content.getTypes().length)
        {
            Ametys.Msg.show({
                title: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENTVALUES_ERROR_TITLE}}",
                msg: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_NO_RIGHT_MSG}}",
                buttons: Ext.Msg.OK,
                icon: Ext.Msg.WARNING
            });
            return;
        }
        
		this._delayedInitialize(config.iconCls || 'ametysicon-clipboard99', 
				config.title || "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_DIALOG_TITLE}}", 
				config.helpMsg1 || "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_DIALOG_HELPMESSAGE1}}" + "<b>'" + Ext.String.escapeHtml(this._content.getTitle()) + "'</b>.", 
				config.helpMsg2 || "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_DIALOG_HELPMESSAGE2}}");

		this._tree.initialize({
			contentId: this._content.getId(),
			checkMandatory: true,
			viewName: this._viewName,
			viewMode: this._viewMode,
            checkByDefault: this._checkByDefault
		});
		
		this._hideTree();
		
		this._box.down('#content-title').setValue(this._content.getTitle() + "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_TITLE_SUFFIX}}");
		this._box.show();
	},
	
	/**
	 * Creates the dialog box if it is not already created
	 * @param {String} iconCls The css classname to display an icon (with a glyph for example)
	 * @param {String} title The title of the dialog box.
	 * @param {String} helpMsg1 The message displayed at the top of the dialog box.
	 * @param {String} helpMsg2 The message displayed at the bottom of the dialog box.
	 * @private
	 */
	_delayedInitialize: function(iconCls, title, helpMsg1, helpMsg2)
	{
		if (!this._initialized)
		{
			this._tree = Ext.create('Ametys.plugins.cms.content.tree.ViewTree', {
				height: 400,
				scrollable: true
			});
			
			this._box = Ext.create('Ametys.window.DialogBox', {
				title: title,
				iconCls: iconCls,
				
				width: 400,
				scrollable: false,
				layout: {
					type: 'vbox',
					align: 'stretch'
				},
				
				items: [{
						xtype: 'component',
						cls: 'a-text',
						html: helpMsg1
					},
					{
						xtype: 'container',
						style: {
							marginTop: '5px',
				            marginBottom: '5px'
				        },
						items: {
							xtype: 'textfield',
							width: 340,
							labelAlign: 'right',
							labelWidth: 70,
							cls: 'ametys',
							name: 'contentTitle',
							fieldLabel: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_TITLE_LABEL}}",
							ametysDescription: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_TITLE_DESC}}",
							itemId: 'content-title',
							allowBlank: false,
							msgTarget: 'side',
							validator: function (value) {
								var s = Ext.String.deemphasize(value);
								if (/^([0-9\-]*|[0-9\-]+.*)[a-z].*$/i.test(s))
								{
									return true;
								}
								else
								{
									return "{{i18n plugin.cms:PLUGINS_CMS_HELPER_COPYCONTENT_TITLE_INVALID}}";
								}
							}
						}
					},
					{
						xtype: 'component',
						cls: 'a-text',
						html: helpMsg2,
						hidden: true
					},
					this._tree
				],
				
				closeAction: 'hide',
				
				defaultFocus: 'content-title',
				selectDefaultFocus: true,
				
				referenceHolder: true,
				defaultButton: 'validate',
				
				buttons : [{
					reference: 'validate',
					text: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_OK}}",
					handler: Ext.bind(this._ok, this),
					itemId: 'btn-ok'
				}, {
					text: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_CANCEL}}",
					handler: Ext.bind(function() {this._box.close();}, this) 
				}, {
					text: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_ADVANCED}}",
					handler: Ext.bind(this._toggleTree, this),
					itemId: 'btn-advanced'
				}],
				
				listeners: {
					resize: {fn: this._onBoxResize, scope: this}
				}
			});
			
			this._initialized = true;
		}
		else
		{
			this._box.setIconCls(iconCls);
			this._box.setTitle(title);
			this._box.items.getAt(0).update(helpMsg1);
			this._box.items.getAt(2).update(helpMsg2);
		}
	},
	
	/**
	 * Hide the tree.
	 * Also updating the show/hide button.
	 */
	_hideTree: function()
	{
		if (this._tree)
		{
			this._tree.hide();
			this._box.items.get(2).hide();
			
			var btn = this._box.down('#btn-advanced');
			if (btn)
			{
				btn.setText("{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_ADVANCED}}");
			}
		}
	},
	
	/**
	 * Show the tree
	 * Also updating the show/hide button.
	 * @private
	 */
	_showTree: function()
	{
		this._tree.show();
		this._box.items.get(2).show();
		
		var btn = this._box.down('#btn-advanced');
		if (btn)
		{
			btn.setText("{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_BTN_BASIC}}");
		}
	},
	
	/**
	 * Hide/show the tree
	 * @private
	 */
	_toggleTree: function()
	{
		if (!this._tree.isVisible())
		{
			this._showTree();
			this._box.items.get(2).show();
			this._tree.selectAndFocusFirstNode();
		}
		else
		{
			this._hideTree();
			this._box.items.get(2).hide();
			this._box.down('#content-title').focus();
		}
	},
	
	/**
	 * This function is called when validating the dialog box.
	 * Aggregate the parameters to make the server request.
	 * Run the duplication action on the server.
	 * @private
	 */
	_ok: function()
	{
		// Title
		var titleField = this._box.down('#content-title');
		if (!titleField.isValid())
		{
			return null;
		}
		
		if (this._tree.isInErrorState())
		{
			Ametys.Msg.show({
				title: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_ERROR_TITLE}}",
				msg: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_TREE_ERROR_MSG}}",
				buttons: Ext.Msg.OK,
				icon: Ext.Msg.ERROR
			});
			return;
		}
		
		var baseContentId = this._content.getId();
		var newContentTitle = titleField.getValue();
		var viewName = this._viewName;
        var fallbackViewName = this._fallbackViewName;
		var viewMode = this._viewMode;
		
		// Add tree values if the tree is displayed.
		var values = this._tree.isVisible() ? this._tree.getValues() : null;
		var valuesToCopy = values ? Ext.JSON.encode(values) : null;
		
		Ametys.data.ServerComm.callMethod({
			role: "org.ametys.cms.workflow.copy.CopyContentClientInteraction",
			methodName: "createContentByCopy",
			parameters: [baseContentId, newContentTitle, valuesToCopy, viewName, fallbackViewName, viewMode, this._workflowInitActionId, this._workflowEditActionId],
			callback: {
				scope: this,
				handler: this._okCb,
                ignoreOnError: false
			},
			waitMessage: {
				msg: "{{i18n PLUGINS_CMS_HELPER_COPYCONTENT_WAIT_MSG}}", 
				target: this._box
			},
			errorMessage: {
				category: Ext.getClassName(this) + '._ok'
			}
		});
	},
	
	/**
	 * Callback function called after copy is processed.
	 * Fires Ametys.message.Message.CREATED message for new created content
	 * @param {Object} response The JSON result from server :
	 * @param {String} response.mainContentId The id of main created content
	 * @param {String[]} response.contentIds The id of created contents
	 * @param {Object} response.report The copy report
	 * @param {Object[]} args The callback parameters passed to the {@link Ametys.data.ServerComm#callMethod} method
	 * @private
	 */
	_okCb: function(response, args)
	{
		if (response != null)
		{
            var contentIds = response.contentIds ? Object.values(response.contentIds) : [];

			if (contentIds.length > 0 && contentIds[0] != '')
			{
				Ext.create("Ametys.message.Message", {
					type: Ametys.message.Message.CREATED,
					targets: {
						id: Ametys.message.MessageTarget.CONTENT,
						parameters: { ids: contentIds }
					}
				});
			}
			
			var report = response.report;
			this._cbFn.call(this._scope, report);
			
			this._box.close();
			
			// CMS-5137 Open directly the main created content after copied
			var mainContentId = response.mainContentId;
			if (mainContentId)
			{
				Ametys.tool.ToolsManager.openTool('uitool-content', {id: mainContentId});
			}
		}
		else
		{
			// In case of bad response, an error message is displayed thanks to the serverComm API
			// but we still want to close the dialog box.
			this._box.close();
		}
	},
	
	/**
	 * Listener to the box resizing event.
	 * Used when the tree visibility is toggled.
	 * @param {Ext.window.Window} box The dialog box
	 * @param {Number} width The window's new width
	 * @param {Number} height The window's new height
	 * @private
	 */
	_onBoxResize: function(box, width, height)
	{
		box.center();
	}
	
});