/*
 *  Copyright 2015 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 related to zones.
 * @private
 */
Ext.define('Ametys.plugins.web.zone.ZoneActions', {
	singleton: true,
	
	/**
	 * Action function to be called by the controller.
	 * This creates a content into the selected page and zone
	 * @param {Ametys.ribbon.element.ui.ButtonController/Object} controller The controller calling this function, or conf.
     * @param {String[]} controller.contentTypes content types to create
     * @param {String} controller.defaultContentTitle name of the content to create
     * @param {String} controller.contentLanguage language of the content
     * @param {Number} controller.initWorkflowActionId init workflow action id
     * @param {String} controller.workflowName workflow name
     * @param {String} controller.siteName site name
     * @param {String} controller.pageId page Id
     * @param {String} controller.zoneName zone name
     * @param {Function} callback callback action
     * If called from a controller, the callback will be done after the default callback, if called directly, it will be done right after content creation.
     * @param {Object} scope scope for the callback
	 */
	addContent: function (controller, callback, scope)
	{
        //contentTypes
        //defaultContentTitle
        //contentLanguage
        //initWorkflowActionId
        //workflowName
        //siteName
        //pageId
        //zoneName
        var config = controller;
        var callbackArgs = [];
        var callbackFn = callback;
        var callbackScope = scope;
        if (controller != null && controller.isButtonController)
        {
            var target = controller.getMatchingTargets()[0];
            if (target != null)
            {
                var btnConfig = controller.getInitialConfig();
                config = {
                    contentTypes: btnConfig.contentTypes,
                    defaultContentTitle: btnConfig.defaultContentTitle || "{{i18n PLUGINS_WEB_ZONE_ADDCONTENTACTION_NEW}}" + " " + btnConfig.label,
                    contentLanguage: target.getParameters().lang,
                    initWorkflowActionId: btnConfig.initWorkflowActionId || 1,
                    workflowName: btnConfig.workflowName,
                    siteName: Ametys.getAppParameters().siteName,
                    pageId: target.getParameters().id,
                    zoneName: target.getParameters()['zone-name']
                }

                callbackArgs = [btnConfig.directEdition === 'true',
                        btnConfig.editWorkflowActionId || 2,
                        btnConfig['viewName'] || 'default-edition',
                        target.getParameters().id,
                        target.getParameters()['zone-name'],
                        target.getParameters()['zone-width']
                    ];
                callbackFn = this._addContentCb;
                callbackScope = this;
            }
        }
        var params = {
            contentType: config.contentTypes,
            contentTitle: config.defaultContentTitle,
            contentLanguage: config.contentLanguage,
            initWorkflowActionId: config.initWorkflowActionId,
            workflowName: config.workflowName,
            additionalWorkflowParameters: {
                'org.ametys.web.repository.site.Site': config.siteName,
                'org.ametys.web.workflow.CreateContentFunction$pageId': config.pageId,
                'org.ametys.web.workflow.CreateContentFunction$zoneName': config.zoneName
            }
        };
        // Create the content
        Ametys.cms.content.ContentDAO.createContent (params, Ext.bind(callbackFn, callbackScope, callbackArgs, 1), this, true);
	},
	
	/**
	 * @private
	 * Callback invoked after creating content
	 * @param {Ametys.cms.content.ContentDAO} content The new created content
	 * @param {Boolean} directEdition true to open content in edition after creation
	 * @param {Number} editWorkflowActionId The id of edit workflow action
     * @param {String} viewName The name of the view to use for content edition
	 * @param {String} pageId The page identifier
     * @param {String} zoneName The zone name where the content is inserted
     * @param {Number} [zoneWidth=0] The zone of the width where the content is inserted
	 */
	_addContentCb: function (content, directEdition, editWorkflowActionId, viewName, pageId, zoneName, zoneWidth)
	{
		if (directEdition)
		{
			// Check if edit action is available
			if (Ext.Array.contains(content.getAvailableActions(), parseInt(editWorkflowActionId)))
			{
				var params = {
					'id': content.getId(),
					'mode': 'edit',
					'edit-workflow-action': parseInt(editWorkflowActionId),
                    'view-name': viewName,
                    'content-width': zoneWidth || 0
				}
				
				// Open content directly in edition.
				Ametys.tool.ToolsManager.openTool('uitool-content', params);
			}
		}
		
		// FIXME get the new created zone item's id to fire modified event with 'zoneitem-id' instead of 'zone-name'
		Ext.create('Ametys.message.Message', {
			type: Ametys.message.Message.MODIFIED,
			targets: [{
				id: Ametys.message.MessageTarget.PAGE,
				parameters: {
					ids: [pageId],
					'zone-name': zoneName
				}
			}]
		});
	},
	
	/**
	 * Action function to be called by the controller.
	 * This creates a content into the selected page and zone
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	addSharedContent: function (controller)
	{
		var target = controller.getMatchingTargets()[0];
		if (target != null)
		{
			var btnConfig = controller.getInitialConfig();
			
			Ametys.cms.uihelper.SelectContentBySearch.open({
	            iconCls: 'ametysicon-text70 decorator-ametysicon-share40',
	            title: "{{i18n PLUGINS_WEB_CONTENT_ADDSHAREDCONTENT_DIALOG_TITLE}}", 

	            helpmessage1: "{{i18n PLUGINS_WEB_HELPER_CHOOSECONTENTBYSEARCH_SEARCH_HELP}}", 
	            helpmessage2: "{{i18n PLUGINS_WEB_HELPER_CHOOSECONTENTBYSEARCH_RESULT_HELP}}", 
	            
	            callback: Ext.bind(this._selectSharedContentCb, this, [target], true),
	            multiple: false,
	            
	            modelId: controller.getInitialConfig('search-model') || 'search-ui.default'
	        });
		}
	},
	
	/**
     * This function is called after selecting content in the search dialog box.
     * Open a dialog box for choosing the content's view.
     * @param {String[]} contentIds The identifiers of selected contents 
     * @param {Ametys.message.MessageTarget} target The page target.
     * @private
     */
	_selectSharedContentCb: function (contentIds, target)
	{
		// Select the view name
		Ametys.cms.uihelper.SelectContentView.open ({
			title: "{{i18n PLUGINS_WEB_CONTENT_ADDSHAREDCONTENT_DIALOG_TITLE}}",
			icon: Ametys.getPluginResourcesPrefix('web') + '/img/content/shared_16.png',
			helpmessage: "{{i18n PLUGINS_WEB_CONTENT_ADDSHAREDCONTENT_PARAM_HINT}}",
			callback: Ext.bind(this._selectViewCb, this, [target], true),
			contentId: contentIds[0]
		})
	},
	
	/**
     * This function is called after selecting the content view
     * Add shared content to selected page and zone.
     * @param {String} contentId The identifier of selected contents 
     * @param {String} viewName The chosen view
     * @param {Ametys.message.MessageTarget} target The page target.
     * @private
     */
	_selectViewCb: function (contentId, viewName, target)
	{
		Ametys.plugins.web.zone.ZoneDAO.addSharedContent(target.getParameters().id, target.getParameters()['zone-name'], contentId, viewName);
	},
	
	/**
	 * Action function to be called by the controller.
	 * Remove a zone item
	 * @param {Ametys.ribbon.element.ui.ButtonController/String} controller The controller calling this function, or the pageId where the zone will be removed (if String, the two next parameters are needeed)
     * @param {String} [zoneName] (only required if called directly)
     * @param {String} [zoneItemId] (only required if called directly)
     * @param {Function} [callback] Method to call when process is finished
	 */
	removeZoneItem: function (controller, zoneName, zoneItemId, callback)
	{
        var pageId = controller;
        if (controller != null && controller.isButtonController)
        {
        var target = controller.getMatchingTargets()[0];
        if (target == null || target.getParameters()['zoneitem-id'] == null)
        {
            // Invalid selection
            Ametys.log.ErrorDialog.display({
                title: "{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_SELECTION_ERROR}}",
                text: "{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_SELECTION_ERROR_DESC}}",
                details: "",
                category: this.self.getName()
            });
            return;
        }

        zoneItemId = target.getParameters()['zoneitem-id'];
        var zoneTarget = target.getSubtarget('zone');
            zoneName = (zoneTarget != null ? zoneTarget.getParameters().name : null);
            pageId = target.getParameters().id;
        }

        Ametys.Msg.confirm("{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_LABEL}}", 
            "{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_CONFIRM}}", 
            Ext.bind(this._confirmRemoveCb, this, [pageId, zoneName, zoneItemId, callback], 1), 
            this
        );
	},
	
	/**
	 * @private
	 * Callback function invoked after the confirm box for set template process is closed
	 * @param {String} answer the user answer
	 * @param {String} pageId the page's id
	 * @param {String} zoneName the zone's name
	 * @param {String} zoneItemId the zone item id
     * @param {Function} [callback] Method to call when process is finished
	 */
	_confirmRemoveCb: function (answer, pageId, zoneName, zoneItemId, callback)
	{
		if (answer == 'yes')
		{
			Ametys.data.ServerComm.callMethod({
				role: "org.ametys.web.repository.page.ZoneDAO",
				methodName: "getZoneItemElementInfo",
				parameters: [zoneItemId],
				callback: {
					scope: this,
					handler: this._getZoneItemElementInfoCb,
					arguments: {
						pageId: pageId,
						zoneName: zoneName,
						zoneItemId: zoneItemId,
                        callback: callback
					}
				},
				errorMessage: {
					category: this.self.getName(),
					msg: "{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_ERROR}}"
				}
			});
		}
	},
	
	/**
	 * @private
	 * Callback function after retrieving unreferenced content of the zone item
	 * @param {Object} elementInfo The zone item element info
	 * @param {Object} args The callback arguments
	 */
	_getZoneItemElementInfoCb: function (elementInfo, args)
	{
		if (elementInfo.type == 'content' && elementInfo.id)
		{
			if (elementInfo.isNew || elementInfo.isShared || elementInfo.isReferenced)
			{
				// Remove content from zone item without confirmation. Delete the content if it is not referenced
				Ametys.plugins.web.zone.ZoneDAO.removeZoneItem (args.pageId, args.zoneName, args.zoneItemId, elementInfo.id, !elementInfo.isReferenced, null, args.callback);
			}
			else
			{
				// Ask for deleting content
				Ametys.Msg.confirm("{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_LABEL}}", 
	                    "{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_REMOVE_CONTENT_CONFIRM}}" + Ext.String.escapeHtml(elementInfo.title) + "{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_REMOVE_CONTENT_CONFIRM2}}", 
	                    Ext.bind(this._confirmRemoveContentCb, this, [args.pageId, args.zoneName, args.zoneItemId, elementInfo, args.callback], 1), 
	                    this
	            );
			}
		}
		else if (elementInfo.type == 'service')
		{
			Ametys.plugins.web.zone.ZoneDAO.removeZoneItem (args.pageId, args.zoneName, args.zoneItemId, null, false, elementInfo.id, args.callback);
		}
	},
	
	/**
	 * @private
	 * Confirm unreferenced content deletion or not
	 * @param {String} answer The user answer
	 * @param {String} pageId The page's id
	 * @param {String} zoneName The zone name
	 * @param {String} zoneItemId The id of zone item to delete
	 * @param {Object} contentInfo The content informations
     * @param {Function} callback A function called at the end of the process
	 */
	_confirmRemoveContentCb: function (answer, pageId, zoneName, zoneItemId, contentInfo, callback)
	{
		if (answer == 'yes')
		{
			if (contentInfo.hasShared)
			{
				// Ask for deleting shared content
				Ametys.Msg.confirm("{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_LABEL}}", 
	                    "{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_CONTENT_HAS_SHARES_CONFIRM}}" + Ext.String.escapeHtml(contentInfo.title) + "{{i18n PLUGINS_WEB_CONTENT_REMOVEZONEITEM_CONTENT_HAS_SHARES_CONFIRM2}}", 
	                    function (ans)
	                    {
							if (ans == 'yes')
							{
								// Remove zone item and content
								Ametys.plugins.web.zone.ZoneDAO.removeZoneItem (pageId, zoneName, zoneItemId, contentInfo.id, true, null, callback);
							}
	                    },
	                    this
	            );
			}
			else
			{
				// Remove zone item and content
				Ametys.plugins.web.zone.ZoneDAO.removeZoneItem (pageId, zoneName, zoneItemId, contentInfo.id, true, null, callback);
			}
		}
		else
		{
			// Remove zone item without removing content
			Ametys.plugins.web.zone.ZoneDAO.removeZoneItem (pageId, zoneName, zoneItemId, contentInfo.id, false, null, callback);
		}
	},
	
	/**
	 * @private
	 * Set the view of the selected content
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	setContentView: function(controller)
	{
		var parentControllerId = controller['parent-controller'];
		var parentController = Ametys.ribbon.RibbonManager.getUI(parentControllerId);
		
		var targets = parentController.getMatchingTargets();
		
		if (targets.length > 0)
		{
			var zoneTarget = targets[0].getSubtarget(Ametys.message.MessageTarget.ZONE);
			var zoneItemTarget = targets[0].getSubtarget(Ametys.message.MessageTarget.ZONE_ITEM); 
			
			// Set the content view only if a different view has been selected.
			if (!controller.isPressed())
		    {
	            var zoneItemId = zoneItemTarget.getParameters().id;
		        var viewName = controller.name;
		        var pageId = targets[0].getParameters().id;
		        
		        parentController.serverCall ('setContentView', 
		        		[zoneItemId, viewName], 
		        		Ext.bind(this._setContentViewCb, this), 
		        		{ 
		        			errorMessage: "{{i18n PLUGINS_WEB_CONTENT_SETCONTENTVIEW_ERROR}}",
		        			arguments: {
		        				pageId: pageId,
		        				zoneName: zoneTarget.getParameters().name,
		        				zoneItemId: zoneItemId
	        				}
	        			}
		        );
		    }
		}
	},
	
	/**
	 * Callback function for the content view setting process
	 * @param {Object} response the server's response
	 * @param {Object} args the callback arguments
	 * @param {String} args.pageId the id of the page
	 */
	_setContentViewCb: function(response, args)
	{
		// Send message.
	    var pageId = args.pageId;
	    
		Ext.create('Ametys.message.Message', {
			type: Ametys.message.Message.MODIFIED,
			targets: [{
				id: Ametys.message.MessageTarget.PAGE,
				parameters: {
					ids: [pageId],
					'zone-name': null,
					'zoneitem-id': args.zoneItemId
				}
			}]
		});
	}
});