/*
 *  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 gathering all the actions the user can perform on aliases
 */
Ext.define('Ametys.plugins.web.alias.AliasActions', {
	singleton: true,
	
	/**
	 * @private
	 * @property {Ametys.window.DialogBox} _box The dialog box for edition/creation of aliases
	 */
	
	/**
	 * @private
	 * @property {Ext.form.Panel} _form The form inside the dialog box
	 */
	
	/**
	 * @private
	 * @property {Boolean} _initialized true when the box is initialized
	 */
	
	/**
	 * @private
	 * @property {String} _mode Can be 'new' or 'edit'
	 */
	
	/**
	 * @private
	 * @property {String} _aliasType the type of alias. Can be "URL" or "PAGE"
	 */
	
	/**
	 * Create an alias
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	addUrl: function(controller)
	{
		this._mode = 'new';
		this._aliasType = "URL";
		this.act();
	},
	
	/**
	 * Create an alias by selecting a target page in current sitemap
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	addPage: function(controller)
	{
		this._mode = 'new';
		this._aliasType = "PAGE";
		this.act();
	},
	
	/**
	 * Edit an alias
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	edit: function (controller)
	{
		var target = controller.getMatchingTargets()[0];
		if (target != null)
		{
			this._mode = 'edit';
			this.act (target);
		}
	},
	
	/**
	 * Open the dialog box to create or edit an alias
	 * @param {Ametys.message.MessageTarget} target the alias target
	 */
	act: function (target)
	{
		this._delayedInitialize();
		
		if (this._mode == 'new')
		{
			// Creation mode
			this._box.setTitle("{{i18n PLUGINS_WEB_HANDLE_ALIAS_CREATE}}");
			this._box.setIconCls('ametysicon-map47 decorator-ametysicon-add64');
		}
		else
		{
			// Edit mode
			this._box.setTitle("{{i18n PLUGINS_WEB_HANDLE_ALIAS_EDIT}}");
			this._box.setConfig('icon', Ametys.getPluginResourcesPrefix('web') + "/img/alias/edit_16.png");
		}
		
		this._initForm(target);
		this._box.show();
	},
	
	/**
	 * Delete an alias
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	deleteAlias: function(controller)
	{
		var targets = controller.getMatchingTargets();
		if (targets.length > 0)
		{
			Ametys.Msg.confirm("{{i18n PLUGINS_WEB_HANDLE_ALIAS_DELETE}}", 
					"{{i18n PLUGINS_WEB_HANDLE_ALIAS_DELETE_CONFIRM}}", 
					Ext.bind(this._doDeleteAlias, this, [targets], 1), 
					this
			);
		}
	},
	
	/**
	 * Delete an alias
	 * @param {String} btn which button was pressed
	 * @param {Object[]} targets The selected aliases
	 */
	_doDeleteAlias: function (btn, targets)
	{
		if (btn == 'yes')
		{
			var ids = [];
			for (var i=0; i < targets.length; i++)
			{
				ids.push(targets[i].getParameters().id);
			}
			
			Ametys.data.ServerComm.callMethod({
				role: "org.ametys.web.alias.AliasDAO",
				methodName: 'deleteAlias',
				parameters: [ids],
				callback: {
					handler: this._deleteAliasCb,
					scope: this,
					arguments: {
						ids: ids
					}
				},
				errorMessage: {
					category: this.self.getName(),
					msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_DELETE_ERROR}}"
				}
			});
		}
	},

	/**
	 * Callback for alias deletion process
	 * @param {Object} response the server's response
	 * @param {Object} args the callback arguments
	 */
	_deleteAliasCb: function (response, args)
	{
		var message = response.msg;
		if (message == "unknown-alias")
		{
			Ametys.Msg.show({
				   title: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_DELETE}}",
				   msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_UNKNOWN}}",
				   buttons: Ext.Msg.OK,
				   icon: Ext.MessageBox.ERROR
			});
			return;
		}
		
		var targets = [];
		var ids = args.ids;
		for (var i=0; i < ids.length; i++)
		{
			var target = Ext.create('Ametys.message.MessageTarget', {
				id: Ametys.message.MessageTarget.ALIAS,
				parameters: {id: ids[i]}
			});
			
			targets.push(target)
		}
		
		if (targets.length > 0)
		{
			Ext.create('Ametys.message.Message', {
				type: Ametys.message.Message.DELETED,
				targets: targets
			});
		}
	},
	
	/**
	 * Move an alias
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	move: function (controller)
	{
		var targets = controller.getMatchingTargets();
		if (targets.length != 1)
		{
			return;
		}
		
		var target = targets[0];
		var id = target.getParameters().id;
	    
	    Ametys.data.ServerComm.callMethod({
			role: "org.ametys.web.alias.AliasDAO",
			methodName: 'moveAlias',
			parameters: [id, controller.role],
			callback: {
				handler: this._moveCb,
				scope: this,
				arguments: {
					id: id
				}
			},
			errorMessage: {
				category: this.self.getName(),
				msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_MOVE_ERROR}}"
			}
		});
	},
	
	/**
	 * Callback for alias moving process
	 * @param {Object} response the server's response
	 * @param {Object} args the callback arguments
	 */
	_moveCb: function(response, args)
	{
		// Trigger the refreshment of the store
	    Ext.create('Ametys.message.Message', {
			type: Ametys.message.Message.MOVED,
			targets: [{
				id: Ametys.message.MessageTarget.ALIAS,
				parameters: {}
			}]
		});
	},
	
	/**
	 * Initialization of the dialog box
	 */
	_delayedInitialize: function()
	{
		if (this._initialized)
		{
	        return;
		}
		
		var formPanel = Ext.create('Ext.form.Panel', {
			labelWidth: 120,
			bodyStyle: 'padding:10px',
			border: false,
			
			defaultType :'textfield',
			
			defaults: {
				cls: 'ametys',
				width: 450,
				labelWidth: 120,
				labelAlign: 'right',
				labelSeparator: '',
				msgTarget: 'side'
			},
			
			scrollable: true,
			items: [ {
						xtype: 'hidden',
		        		name: 'id'
					 },
					 {
						xtype: 'hidden',
						name: 'type',
						value: 'PAGE'
					 },
					 {
						 name: 'url',
						 fieldLabel: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_ORIGIN_URL}}",
						 ametysDescription: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_ORIGIN_URL_DESC}}",
						 regex: new RegExp('^/.+$'),
						 regexText: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_INVALID_URL}}"
					 },
					 {
						 xtype: 'edition.select-page',
						 siteContext: Ametys.web.form.widget.SelectPage.SITE_CONTEXT_ALL,
						 sitemapContext: Ametys.web.form.widget.SelectPage.SITEMAP_CONTEXT_ALL,
						 name: 'target-page',
						 fieldLabel: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_TARGET_PAGE}}",
						 ametysDescription: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_TARGET_PAGE_DESC}}",
						 allowBlank: false,
						 allowCreation: true,
						 hidden: true
					 },
					 {
						 name: 'target-url',
						 fieldLabel: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_TARGET_URL}}",
						 ametysDescription: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_TARGET_URL_DESC}}",
						 allowBlank: false,
						 regex: new RegExp ('^(https?://|/).+$'), // Copy of the regexp in org.ametys.web.alias.AliasDAO#TARGET_URL_PATTERN
					     regexText: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_INVALID_TARGET_URL}}"
					 },
					 {
						 xtype:'edition.date',
						 name: 'expiration_date',
						 fieldLabel: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_EXPIRATION_DATE}}",
						 ametysDescription: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_EXPIRATION_DATE_DESC}}"
					 }
			]
		});
		
		this._form = formPanel.getForm();
		
		this._box = Ext.create('Ametys.window.DialogBox', {
			title:"{{i18n PLUGINS_WEB_HANDLE_ALIAS_CREATE}}",
			iconCls: 'ametysicon-map47',
			
			layout:'fit',
			width: 520,
			
			items : [ formPanel ],
			
			defaultFocus: formPanel.getForm().findField('url'),
			
			referenceHolder: true,
			defaultButton: 'validate',
			
			closeAction: 'hide',
			buttons : [{
				reference: 'validate',
				text :"{{i18n PLUGINS_WEB_HANDLE_ALIAS_BTN_OK}}",
				handler : Ext.bind(this._ok, this)
			}, {
				text :"{{i18n PLUGINS_WEB_HANDLE_ALIAS_BTN_CANCEL}}",
				handler : Ext.bind(this._cancel, this)
			}]
		});
		
		this._initialized = true;
	},
	
	
	/**
	 * @private Initialize the form param {Object} the first matching target
	 */
	_initForm: function (target)
	{
		if (this._mode == 'new')
		{
			var form = this._form;
			
			form.reset();
			form.clearInvalid();
			
            this._setAliasType (form, this._aliasType);
            
		    var date = Ext.Date.add(new Date(), Ext.Date.YEAR, 1);
		    form.findField('expiration_date').setValue(date);
		}
		else
		{
			// Get selected alias info
			Ametys.data.ServerComm.callMethod({
				role: "org.ametys.web.alias.AliasDAO",
				methodName: 'getAlias',
				parameters: [target.getParameters().id],
				callback: {
					handler: this._initFormCb,
					scope: this
				},
				errorMessage: {
					category: this.self.getName(),
					msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_SELECTION_ERROR}}"
				}
			});
		}
	},
	
    /**
     * @private
     * Apply the given alias type to the form
     * @param {Ext.form.Panel} form The form where to apply
     * @param {String} aliasType The alias type to apply
     */
	_setAliasType: function (form, aliasType)
	{
		form.findField('type').setValue(aliasType);
		
		var isPageType = aliasType == 'PAGE';
		
		form.findField("target-url").setVisible(!isPageType);
		form.findField("target-url").setDisabled(isPageType);
		form.findField("target-page").setVisible(isPageType);
		form.findField("target-page").setDisabled(!isPageType);
	},
	
	/**
	 * @private 
	 * Callback for the form initialization process
	 * @param {Object} alias the alias ' properties
	 * @param {Object} args the callback arguments
	 */
	_initFormCb: function(alias, args)
	{
		var form = this._form;
		
		form.findField('id').setValue(alias.id);
		form.findField('url').setValue(alias.url);
		
		var type = alias.type;
		this._setAliasType (form, alias.type);
		
		if (type == 'PAGE')
		{
			form.findField('target-page').setValue(alias.target);
		}
		else
		{
			form.findField('target-url').setValue(alias.target);
		}
		
	    var date = Ext.Date.parse(alias.expirationDate, Ext.Date.patterns.ISO8601DateTime);
	    form.findField('expiration_date').setValue(date);
	},

	/**
	 * Function called when clicking on 'Ok' button
	 */
	_ok: function ()
	{
		if (this._form.isValid())
		{
			var relHref = this._form.findField('url').getValue();
			if (/^\/([a-z]{2})\/(.*)\.html$/.test(relHref))
			{
				var siteName = Ametys.getAppParameter('siteName');
				var lang = RegExp.$1;
				var path = RegExp.$2;
				
				Ametys.data.ServerComm.callMethod({
					role: "org.ametys.web.repository.page.SitemapDAO",
					methodName: 'convertPathToId',
					parameters: [siteName, lang, path],
					callback: {
						handler: this._checkPathCb,
						scope: this
					},
					errorMessage: false
				});
			}
			else
			{
				this._doAction ();
			}
		}
	},
	
	/**
	 * Function called after checking if the page with this path exist in sitemap
	 * @param {String} pageId The page id or null if not found
	 */
	_checkPathCb: function (pageId)
	{
		if (pageId != null)
		{
			Ametys.Msg.show({
				   title: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_PAGE_EXISTS}}",
				   msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_PAGE_EXISTS_HINT}}",
				   buttons: Ext.Msg.YESNO,
				   icon: Ext.MessageBox.WARNING,
				   fn: Ext.bind(this._doAction, this)
			});
			return;
		}
		
		this._doAction();
	},
	
	
	/**
	 * @private
	 * Create or update an alias
	 * @param {String} btn which button was pressed
	 */
	_doAction: function (btn)
	{
		if (btn == null || btn == 'yes')
		{
			var form = this._form;
			
			var type = form.findField('type').getValue();
			var url = form.findField('url').getValue();
			var target = type == 'PAGE' ? form.findField('target-page').getValue() : form.findField('target-url').getValue();
			var siteName = Ametys.getAppParameter('siteName');
			
			if (form.findField('expiration_date').getValue() != '')
			{
				var date = form.findField('expiration_date').getValue();
				date = Ext.Date.format(date, Ext.Date.patterns.ISO8601DateTime);
			}
			
			if (this._mode == 'new')
			{
				// Create alias
				Ametys.data.ServerComm.callMethod ({
					role: "org.ametys.web.alias.AliasDAO",
					methodName: 'createAlias',
					parameters: [type, url, target, siteName, date],
					callback: {
						handler: this._createAliasCb,
						scope: this
					},
					errorMessage: {
						category: this.self.getName(),
						msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_CREATE_ERROR}}"
					}
				});
			}
			else
			{
				var id = form.findField('id').getValue();
				
				// Update alias
				Ametys.data.ServerComm.callMethod({
					role: "org.ametys.web.alias.AliasDAO",
					methodName: 'updateAlias',
					parameters: [id, type, url, target, siteName, date],
					callback: {
						handler: this._updateAliasCb,
						scope: this
					},
					errorMessage: {
						category: this.self.getName(),
						msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_EDIT_ERROR}}"
					}
				});
			}
			
		}
	},
	
	/**
	 * Callback after creating alias
	 * @param {Object} response the server's response
	 * @param {Object} args the callback arguments
	 */
	_createAliasCb: function (response, args)
	{
		var message = response.msg;
		
		if (message == 'already-exists')
		{
			Ametys.Msg.show({
				   title: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_CREATE}}",
				   msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_CREATE_ALREADY_EXISTS}}",
				   buttons: Ext.Msg.OK,
				   icon: Ext.MessageBox.ERROR
			});
			return;
		}
		else if (message == 'invalid-url')
		{
			this._form.findField('url').markInvalid("{{i18n PLUGINS_WEB_HANDLE_ALIAS_INVALID_URL}}");
			return;
		}
		else if (message == 'invalid-target-url')
		{
			this._form.findField('target-url').markInvalid("{{i18n PLUGINS_WEB_HANDLE_ALIAS_INVALID_TARGET_URL}}");
			return;
		}
		
		this._box.hide();
		
		Ext.create('Ametys.message.Message', {
			type: Ametys.message.Message.CREATED,
			targets: [{
				id: Ametys.message.MessageTarget.ALIAS,
				parameters: {'id': response.id}
			}]
		});
		
		var tool = Ametys.tool.ToolsManager.getTool('uitool-alias');
    	if (tool == null)
    	{
    		Ametys.tool.ToolsManager.openTool('uitool-alias', {selectedAliasIds: [response.id]});
    	}
	},
	
	/**
	 * Callback after updating alias
	 * @param {Object} response the server's response
	 * @param {Object} args the callback arguments
	 */
	_updateAliasCb: function (response, args)
	{
		var message = response.msg;
		
		if (message == "unknown-alias")
		{
			Ametys.Msg.show({
				   title: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_EDIT}}",
				   msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_UNKNOWN}}",
				   buttons: Ext.Msg.OK,
				   icon: Ext.MessageBox.ERROR
			});
			return;
		}
		else if (message == 'already-exists')
		{
			Ametys.Msg.show({
				   title: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_EDIT}}",
				   msg: "{{i18n PLUGINS_WEB_HANDLE_ALIAS_CREATE_ALREADY_EXISTS}}",
				   buttons: Ext.Msg.OK,
				   icon: Ext.MessageBox.ERROR
			});
			return;
		}
		else if (message == 'invalid-url')
		{
			this._form.findField('url').markInvalid("{{i18n PLUGINS_WEB_HANDLE_ALIAS_INVALID_URL}}");
			return;
		}
		else if (message == 'invalid-target-url')
		{
			this._form.findField('target-url').markInvalid("{{i18n PLUGINS_WEB_HANDLE_ALIAS_INVALID_TARGET_URL}}");
			return;
		}
		
		this._box.hide();
		
		Ext.create('Ametys.message.Message', {
			type: Ametys.message.Message.MODIFIED,
			targets: [{
				id: Ametys.message.MessageTarget.ALIAS,
				parameters: {'id': response.id}
			}]
		});;
	},
	
	/**
	 * @private
	 * Cancel the update/creation process
	 */
	_cancel: function ()
	{
		this._box.hide();
	}
});