/*
 *  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.
 */

/**
 * Class to handle link insertion in inline editor
 * @private
 */
Ext.define('Ametys.plugins.cms.editor.Links', {
	singleton: true,

    /**
     * @private
     * @type {Boolean} true to allow drag and drop in attachments and resources tree
     */
    _allowDragAndDrop: true,
    
	/**
	 * @property {Object[]} The registered handlers
	 */
	handlers: [],
	
	/**
	 * Add a link handler for a type of link
	 * @param {String} type The type of the link (mail, resource, ...) concerned by this handler. Can be null for default type.
	 * @param {Ametys.cms.editor.LinkHandler} handler The handler link handler
	 */
	addLinkHandler: function (type, handler)
	{
		this.handlers[type] = handler;
	},
	
	/**
	 * Get the link handler associated with the type
	 * @param {String} type The type of link (mail, resource, ...). Can be null to get the default handler.
	 * @return {Ametys.cms.editor.LinkHandler} The link handler
	 */
	getLinkHandler: function (type)
	{
		return this.handlers[type];
	},
	
	/**
	 * Register "a" as a valid tag
	 */
	initialize: function ()
	{
		this.addLinkHandler (null, Ext.create('Ametys.plugins.cms.editor.Links.WebLinkHandler', {}));
	},
	
	/**
	 * Remove a link
	 * @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	remove: function(controller)
	{
	    var editor = controller.getCurrentField().getEditor();
		editor.execCommand('mceBeginUndoLevel');
		editor.execCommand('UnLink');
		editor.execCommand('mceEndUndoLevel');
	},
	
	//------------------------------------------------------//
	//						WEB LINK						//
	//------------------------------------------------------//
	
	/**
	 * Insert a web external link
	 * @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	insertWebLink: function(controller)
	{
		var currentUrl = "";
		var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
		if (node != null && (node.getAttribute("data-ametys-type") == null || node.getAttribute("data-ametys-type") == ""))
		{
			currentUrl = node.getAttribute("href");
		}
		
		this._doInsertWebLink (currentUrl == '' ? 'http://' : '');
	},

	/**
	 * Open dialog to enter the external link url
	 * @param {String} currentUrl The default URL value
	 * @private
	 */
	_doInsertWebLink: function (currentUrl)
	{
		Ametys.helper.EnterURL.open({
                iconCls: "ametysicon-link23",
				title: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_LINK}}",
				helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_URL_DESC}}",
				footermessage: "{{i18n PLUGINS_CMS_HELPER_ENTERURL_HINT}}",
				callback: this._insertWebLinkCb,
				defaultValue: currentUrl
        });	
	},

	/**
	 * Callback function called when user has entered the link URL. Inserts the link to the cursor position
	 * @param {String} url The entered URL
	 * @private
	 */
	_insertWebLinkCb: function(url)
	{
		if (url != null)
		{
		    // FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
			tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
		
			var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
			if (node == null && tinyMCE.activeEditor.selection.isCollapsed())
			{
				tinyMCE.activeEditor.execCommand('mceInsertContent', false, "<a href='#'>" + url + "{$caret}</a> ");

				node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
				tinyMCE.activeEditor.selection.select(node);
			}
		
			tinyMCE.activeEditor.execCommand('mceInsertLink', false, { "data-ametys-href": url, "href": url, "class": "external", "target": "_blank", "data-ametys-type": "", "_mce_ribbon_select": "1" });
			tinyMCE.activeEditor.selection.collapse();
		
			tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
		}
		// Delayed to wait for the dialog box to hide.
		window.setTimeout(function() {tinyMCE.activeEditor.focus();}, 100);
	},
	
	//------------------------------------------------------//
	//						MAIL LINK						//
	//------------------------------------------------------//
	
	/**
	 * Initialize function to add a link handler for mail
	 */
	initializeMailLink: function (controller)
	{
		this.addLinkHandler ('mail', Ext.create('Ametys.plugins.cms.editor.Links.MailLinkHandler', {}));
	},
	
	/**
	 * Insert a link of type 'mailto'
	 * @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	insertMailtoLink: function (controller)
	{
	    var editor = controller.getCurrentField().getEditor(); 
	    this._insertMailtoLink(editor);
	},
    
    /**
     * @private
     * Insert a link of type 'mailto'
     * @param {tinymce.Editor} editor The tinymce active editor
     */
    _insertMailtoLink: function(editor)
    {
        var currentUrl = "";
        var node = editor.dom.getParent(editor.selection.getNode(), 'a');
        if (node != null && (node.getAttribute("data-ametys-type") == "mail"))
        {
            currentUrl = node.getAttribute("href");
        }
        
        this._doInsertMailtoLink(currentUrl);
    },
	
	/**
	 * Open dialog to enter the mail address
	 * @param {String} currentUrl The default mail
	 * @private
	 */
	_doInsertMailtoLink:  function(currentUrl)
	{
		currentUrl = currentUrl || '';
		if (currentUrl.indexOf('mailto:') == 0)
		{
			currentUrl = currentUrl.substring('mailto:'.length);
		}
		
		Ametys.helper.EnterURL.open({
                iconCls: "ametysicon-dark4",
	            title: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_MAILTO}}",
	            helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_MAILTO_DESC}}",
	            footermessage: "{{i18n PLUGINS_CMS_HELPER_ENTERURL_EMAIL_HINT}}",
	            callback: this._insertMailtoLinkCb,
	            defaultValue: currentUrl,
	            regex: '^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9][A-Za-z0-9]+)+$',
	            regexText: "{{i18n CONTENT_EDITION_LINK_INSERT_MAILTO_INVALID_EMAIL}}"
        });
	},
	
	/**
	 * Callback function called when user has entered mailto link. Inserts the link to the cursor position.
	 * @param {String} email The entered email
	 * @private
	 */
	_insertMailtoLinkCb: function(email)
	{
	    // FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
	    tinyMCE.activeEditor.focus();
	    if (email != null)
	    {
	        var url = 'mailto:' + email;
	        
	        tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
	        
	        var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
	        if (node == null && tinyMCE.activeEditor.selection.isCollapsed())
	        {
	            tinyMCE.activeEditor.execCommand('mceInsertContent', false, "<a href='#'>" + email + "{$caret}</a> ");

				node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
				tinyMCE.activeEditor.selection.select(node);
	        }
	        
	        tinyMCE.activeEditor.execCommand('mceInsertLink', false, { "data-ametys-href": url, "href": url, "class": "mailto", "data-ametys-type": "mail", "_mce_ribbon_select": "1" });
	        tinyMCE.activeEditor.selection.collapse();
	        
	        tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
	    }	

		// Delayed to wait for the dialog box to hide.
		window.setTimeout(function() {tinyMCE.activeEditor.focus();}, 100);
	},
	
    //------------------------------------------------------//
    //                     PHONE LINK                       //
    //------------------------------------------------------//
    
    /**
     * Initialize function to add a link handler for phone
     */
    initializePhoneLink: function (controller)
    {
        this.addLinkHandler ('phone', Ext.create('Ametys.plugins.cms.editor.Links.PhoneLinkHandler', {}));
    },
    
    /**
     * Insert a link of type 'tel'
     * @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
     */
    insertPhoneLink: function (controller)
    {
        var editor = controller.getCurrentField().getEditor(); 
        this._insertPhoneLink(editor);
    },
    
    /**
     * @private
     * Insert a link of type 'tel'
     * @param {tinymce.Editor} editor The tinymce active editor
     */
    _insertPhoneLink: function(editor)
    {
        var currentUrl = "";
        var node = editor.dom.getParent(editor.selection.getNode(), 'a');
        if (node != null && (node.getAttribute("data-ametys-type") == "phone"))
        {
            currentUrl = node.getAttribute("href");
        }
        
        this._doInsertPhoneLink(currentUrl);
    },
    
    /**
     * Open dialog to enter the phone number
     * @param {String} currentUrl The default number
     * @private
     */
    _doInsertPhoneLink:  function(currentUrl)
    {
        currentUrl = currentUrl || '';
        if (currentUrl.indexOf('tel:') == 0)
        {
            currentUrl = currentUrl.substring('tel:'.length);
        }
        
        Ametys.helper.EnterURL.open({
                iconCls: "ametysicon-phone",
                title: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_PHONE}}",
                helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_PHONE_DESC}}",
                footermessage: "{{i18n PLUGINS_CMS_HELPER_ENTERURL_PHONE_HINT}}",
                fieldlabel: "{{i18n PLUGINS_CMS_HELPER_ENTERURL_PHONE_FIELD_LABEL}}",
                callback: this._insertPhoneLinkCb,
                defaultValue: currentUrl,
                regex: '^\\+?\\s*(\\d+\\s?){2,}$',
                regexText: "{{i18n CONTENT_EDITION_LINK_INSERT_PHONE_INVALID_NUMBER}}"
        });
    },
    
    /**
     * Callback function called when user has entered phone link. Inserts the link to the cursor position.
     * @param {String} phone The entered phone
     * @private
     */
    _insertPhoneLinkCb: function(phone)
    {
        // FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
        tinyMCE.activeEditor.focus();
        if (phone != null)
        {
            var url = 'tel:' + phone;
            
            tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
            
            var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
            if (node == null && tinyMCE.activeEditor.selection.isCollapsed())
            {
                tinyMCE.activeEditor.execCommand('mceInsertContent', false, "<a href='#'>" + phone + "{$caret}</a> ");

                node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
                tinyMCE.activeEditor.selection.select(node);
            }
            
            tinyMCE.activeEditor.execCommand('mceInsertLink', false, { "data-ametys-href": url, "href": url, "class": "phone", "data-ametys-type": "phone", "_mce_ribbon_select": "1" });
            tinyMCE.activeEditor.selection.collapse();
            
            tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
        }   

        // Delayed to wait for the dialog box to hide.
        window.setTimeout(function() {tinyMCE.activeEditor.focus();}, 100);
    },
    
	//------------------------------------------------------//
	//					RESOURCE LINK						//
	//------------------------------------------------------//
	
	/**
	 * Initialize function to add a link handler for resources
	 * @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	initializeResourcesLink: function (controller)
	{
		this.addLinkHandler ('explorer', Ext.create('Ametys.plugins.cms.editor.Links.ResourceLinkHandler', {}));
	},
	
	/**
	 * Insert a link from the resource explorer.
	 * @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	insertResourcesLink: function(controller)
	{
		var currentId = null;
		var editor = controller.getCurrentField().getEditor();
		var node = editor.dom.getParent(editor.selection.getNode(), 'a');
		if (node != null && (node.getAttribute("data-ametys-type") == "explorer"))
		{
			currentId = node.getAttribute("data-ametys-href");
		}

		this._doInsertResourcesLink(currentId);
	},

	/**
	 * Open dialog to select the resource from the explorer
	 * @param {String} currentId The resource id to select when opening the dialog box
	 * @private
	 */
	_doInsertResourcesLink: function(currentId)
	{
		Ametys.cms.uihelper.ChooseResource.open({
			title: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_RESOURCE_LABEL}}",
			helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_INSERT_RESOURCE_DESCRIPTION}}",
			callback: this._insertResourcesLinkCb,
			filter: null,
			currentId: currentId,
            allowDragAndDrop: this._allowDragAndDrop
		});
	},
	
	/**
	 * Callback function called when user has selected the resource to link. Inserts the link to the current cursor position
	 * @param {String} id Id of the resource
	 * @param {String} filename File name of the resource
	 * @param {String} filesize File length of the resource
	 * @param {String} viewHref The URL to view the resource file
	 * @param {String} downloadHref The URL to download the resource file
	 * @param {Object} actionResult The result of the upload action. Can be null
	 * @param {String} [type='explorer'] The type of the resource to insert.
	 * @private
	 */
	_insertResourcesLinkCb: function(id, filename, filesize, viewHref, downloadHref, actionResult, type)
	{
		type = type || 'explorer';
		
		if (id)
		{
		    // FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
			tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');

			var node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
			if (node == null && tinyMCE.activeEditor.selection.isCollapsed())
			{
				var text = "{{i18n PLUGINS_CMS_EDITOR_LINK_DOWNLOAD}} «" + filename + "» (" + Ext.util.Format.fileSize(filesize) + ")"; 
				tinyMCE.activeEditor.execCommand('mceInsertContent', false, "<a href='#'>" + text + "{$caret}</a>");

				node = tinyMCE.activeEditor.dom.getParent(tinyMCE.activeEditor.selection.getNode(), 'a');
				tinyMCE.activeEditor.selection.select(node);
			}

			tinyMCE.activeEditor.execCommand('mceInsertLink', false, { "data-ametys-href": id, href: downloadHref, "class": "download", "data-ametys-type": type, "_mce_ribbon_select" : "1" });
			tinyMCE.activeEditor.selection.collapse();

			tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
		}

		// Delayed to wait for the dialog box to hide.
		window.setTimeout(function() {tinyMCE.activeEditor.focus();}, 100);
	},
	
	/**
	 * Insert a link from the resource explorer in a HTML expert code
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	insertResourcesLinkHtmlExpert: function (controller)
	{
		Ametys.cms.uihelper.ChooseResource.open({
		    title: "{{i18n PLUGINS_CMS_HTMLEXPERT_LINK_EXPLORER_BOX_TITLE}}",
		    helpmessage: "{{i18n PLUGINS_CMS_HTMLEXPERT_LINK_EXPLORER_BOX_HINT}}",
		    callback: this._insertResourcesLinkHtmlExpertCb,
		    filter: null
		});
	},
	
	/**
	 * Callback function called when user has selected the resource to link. Inserts the link to the current cursor position in the HTML expert code
	 * @param {String} id Id of the resource
	 * @param {String} filename File name of the resource
	 * @param {String} filesize File length of the resource
	 * @param {String} viewHref The URL to view the resource file
	 * @param {String} downloadHref The URL to download the resource file
	 * @private
	 */
	_insertResourcesLinkHtmlExpertCb: function(id, filename, filesize, viewHref, downloadHref)
	{
		if (id != null)
		{
			Ametys.plugins.cms.editor.HTMLExpert.insertAtCaret("${" + "type:explorer#url:" + id + "#download:false}");
		}
	},

	//------------------------------------------------------//
	//					ATTACHMENT LINK						//
	//------------------------------------------------------//
	
	/**
	 * Initialize function to add a link handler for attachments
	 * @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	initializeAttachmentLink: function (controller)
	{
		this.addLinkHandler ('attachment-content', Ext.create('Ametys.plugins.cms.editor.Links.AttachmentLinkHandler', {}));
	},
	
	/**
	 * Insert a link from the attachments of the content.
	 * @param controller {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	insertAttachmentLink: function(controller)
	{
		var contentTarget = Ametys.message.MessageBus.getCurrentSelectionMessage().getTarget(Ametys.message.MessageTarget.CONTENT);
		if (contentTarget)
		{
			var actionId = controller.getWorkflowActionId();
			
			var currentId = (this._currentNode && this._currentNode.getAttribute('data-ametys-type') == 'attachment-content') ? this._currentNode.getAttribute('data-ametys-href') : null;
			
			this._doInsertAttachmentLink(contentTarget, currentId, actionId);
		}
	},
	
	/**
	 * Open a dialog box to select a content attachment.
	 * @param {String|Ametys.message.MessageTarget} content The content target (attachments' owner) or the content's id.
	 * @param {String} currentId The resource id to select when opening the dialog box
	 * @param {String} [actionId] The id of workflow action to execute if any.
	 * @private
	 */
	_doInsertAttachmentLink: function(content, currentId, actionId)
	{
        var contentId = Ext.isString(content) ? content : content.getParameters().id;
		var callback = Ext.bind(this._selectAttachmentCb, this, [contentId, actionId], true);
		
		Ametys.cms.uihelper.ChooseAttachmentFile.open({
			iconCls: 'ametysicon-clip26',
			title: "{{i18n PLUGINS_CMS_EDITOR_LINK_FILE_LABEL}}",
			helpmessage: "{{i18n PLUGINS_CMS_EDITOR_LINK_FILE_DESCRIPTION}}",
			ownerId: contentId,
			callback: callback,
			value: currentId,
			allowCreation: true,
            allowDragAndDrop: this._allowDragAndDrop,
            insertAttachmentCallback: Ext.bind(this._changeContentWorkflow, this, [contentId, actionId, Ext.isString(content) ? null : content], 1)
		});
	},
	
	/**
	 * Callback function called when user has selected the attachment to link. Inserts the link to the current cursor position
	 * @param {String} fileid Id of the resource
	 * @param {String} filename File name of the resource
	 * @param {String} filesize File length of the resource
	 * @param {String} viewHref The URL to view the resource file
	 * @param {String} downloadHref The URL to download the resource file
	 * @param {String} contentId The id of the content.
	 * @param {String} [actionId] The id of workflow action to execute if any.
	 * @private
	 */
	_selectAttachmentCb: function(fileid, filename, filesize, viewHref, downloadHref, contentId, actionId)
	{
		this._insertResourcesLinkCb(fileid, filename, filesize, viewHref, downloadHref, null, 'attachment-content');
	},
	
	/**
	 * Insert a link from the attachments of a content in a HTML expert code
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller calling this function
	 */
	insertAttachmentLinkHtmlExpert: function(controller)
	{
		var contentTarget = Ametys.message.MessageBus.getCurrentSelectionMessage().getTarget(Ametys.message.MessageTarget.CONTENT);
		if (contentTarget)
		{
			var ownerId = contentTarget.getParameters()['id'];
			var actionId = controller.getInitialConfig('workflow-action-id');
			var callback = Ext.bind(this._insertAttachmentLinkHtmlExpertCb, this, [ownerId, actionId], true);
			
			Ametys.cms.uihelper.ChooseAttachmentFile.open({
				icon: Ametys.getPluginResourcesPrefix('cms') + '/img/content/attachments/attachment_16.png',
				title: "{{i18n PLUGINS_CMS_HTMLEXPERT_LINK_ATTACHMENT_BOX_TITLE}}",
				helpmessage: "{{i18n PLUGINS_CMS_HTMLEXPERT_LINK_ATTACHMENT_BOX_HINT}}",
				ownerId: ownerId,
				callback: callback,
				allowCreation: true,
				rightContext: '/contents/' + contentTarget.getParameters().name
			});
		}
	},
	
	/**
	 * Callback function called when user has selected the attachment to link. Inserts the link to the current cursor position in the HTML expert code
	 * @param {String} id Id of the resource
	 * @param {String} filename File name of the resource
	 * @param {String} filesize File length of the resource
	 * @param {String} viewHref The URL to view the resource file
	 * @param {String} downloadHref The URL to download the resource file
	 * @param {String} contentId The id of the content.
	 * @param {String} [actionId] The id of workflow action to execute if any.
	 * @private
	 */
	_insertAttachmentLinkHtmlExpertCb: function(id, filename, filesize, viewHref, downloadHref, contentId, actionId)
	{
		if (id != null)
		{
			Ametys.plugins.cms.editor.HTMLExpert.insertAtCaret("${" + "type:attachment-content#url:" + id + "#download:false}");
			
			if (actionId)
			{
				this._changeContentWorkflow(contentId, actionId);
			}
		}
	},
	
	/**
	 * Executes a workflow action on content
     * @param {String} resourceId The id of the attached resource
	 * @param {String} contentId The id of the content
	 * @param {Number} actionId The id of workflow action to execute
	 * @param {Object/Ametys.message.MessageTarget} [contentTarget] The content target or its configuration object. Can be null, but should be provided if available.
	 * @private
	 */
	_changeContentWorkflow: function(resourceId, contentId, actionId, contentTarget)
	{
        if (!actionId)
        {
            return;
        }
        
		contentTarget = contentTarget || {
			id: Ametys.message.MessageTarget.CONTENT,
			parameters: {ids: [contentId]}
		};
		
		var me = this;
		var targetCreatedCb = function(targets) {
			var target = targets[0];
			
			var params = {
				contentId: contentId,
				id: contentId, 
				'with-contents': '/_plugins/cms/contents/info'
			};
				
			Ext.create('Ametys.message.Message', {
				type: Ametys.message.Message.WORKFLOW_CHANGING,
				targets: [target]
			});
			
			Ametys.data.ServerComm.send({
				plugin: 'cms',
				url: 'do-action/' + actionId,
				parameters: params,
				priority: Ametys.data.ServerComm.PRIORITY_MAJOR,
				errorMessage: true,
				callback: {
					handler: me._changeContentWorkflowCb,
					scope: me,
					arguments: [target]
				}
			});
		};
		
		if (!(contentTarget instanceof Ametys.message.MessageTarget))
		{
			Ametys.message.MessageTargetFactory.createTargets(contentTarget, targetCreatedCb);
		}
		else
		{
			targetCreatedCb([contentTarget]);
		}
	},
	
	/**
	 * @protected
	 * Callback function called after executing worklow action
	 * Override if specific behavior is needed.
	 * @param {Object} response The XML response provided by the {@link Ametys.data.ServerComm}
	 * @param {Object[]} params The callback parameters passed to the {@link Ametys.data.ServerComm#send} method
	 */
	_changeContentWorkflowCb: function(response, params)
	{
		var contentTarget = params[0];
		
		Ext.create('Ametys.message.Message', {
			type: Ametys.message.Message.WORKFLOW_CHANGED,
			targets: [contentTarget]
		});
	},
	
	//------------------------------------------------------//
	//				MISC INTERNAL METHODS					//
	//------------------------------------------------------//
	
	/**
	 * Enable/disable controller if the current selected node is a link
	 * @param {Ametys.ribbon.element.ui.ButtonController} controller The controller
	 * @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
	 * @param {HTMLElement} node The current selected node. Can be null.
	 */
	linkSelectionListener: function (controller, field, node)
	{
		this._currentNode = node;
	},
	
	// ---------------------------------------- //
	//               EDIT LINK                  //
	// ---------------------------------------- //
	
    /**
     * Open the edit link dialog.
     * @param {Ext.form.field.Text} input The input text.
     * @param {Ext.event.Event} e The event object.
     */
    editLink: function(input, e)
	{
        if (this._currentNode != null)
        {
            var type = this._currentNode.getAttribute('data-ametys-type');
            var href = this._currentNode.getAttribute('data-ametys-href') || this._currentNode.getAttribute('href');
            
            if (this.getLinkHandler(type) != null)
            {
            	this.getLinkHandler(type).edit(href);
            }
        }
	},
	
    /**
     * Enable/disable the edit link controller.
     * @param {Ametys.ribbon.element.ui.FieldController} controller The controller.
     * @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
     * @param {HTMLElement} node The current selected node. Can be null.
     */
	editLinkListener: function(controller, field, node)
    {
        var handler = this._currentNode != null ? this.getLinkHandler(this._currentNode.getAttribute("data-ametys-type")) : null;
        if (this._currentNode && handler && Ext.isFunction(handler.edit))
        {
            controller.enable();
        }
        else
        {
            controller.disable();
        }
    },
	
    // ---------------------------------------- //
    //              REMOVE LINK                 //
    // ---------------------------------------- //
    
    /**
     * Remove the selected link.
     * @param {Ext.form.field.Text} input The input text.
     * @param {Ext.event.Event} e The event object.
     */
    removeLink: function(input, e)
    {
        if (this._currentNode != null)
        {
            // FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
            tinyMCE.activeEditor.focus();
            tinyMCE.activeEditor.execCommand('mceBeginUndoLevel');
            tinyMCE.activeEditor.execCommand('UnLink');
            tinyMCE.activeEditor.execCommand('mceEndUndoLevel');
        }
    },
    
    // ---------------------------------------- //
    //               OPEN LINK                  //
    // ---------------------------------------- //
    
    /**
     * Enable/disable controller and set value according to the selected link.
     * @param {Ametys.ribbon.element.ui.FieldController} controller The controller.
     * @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
     * @param {HTMLElement} node The current selected node. Can be null.
     */
    openLinkListener: function(controller, field, node)
    {
    	this._currentNode = node;
        
        if (this._currentNode)
        {
        	var type = this._currentNode.getAttribute('data-ametys-type');
        	var value = this._currentNode.getAttribute('data-ametys-href') || this._currentNode.getAttribute('href');
        	var handler = this.getLinkHandler(type);
        	
        	type = handler != null ? handler.getTypeName() : type;
        	var title = handler != null ? handler.getTitle(value) : value;
        	var desc = handler != null ? handler.getDescription(value) : '';
        	
            if (this._currentNode.getAttribute("href") != '')
            {
        	   controller.setValue('(' + type + ') <a onclick="javascript:Ametys.plugins.cms.editor.Links.openLink(); return false;" href="">' + title + '</a>');
            }
            else
            {
                controller.setValue('(' + type + ') ' + title);
            }
            controller.setDescription (desc);
        }
        else
        {
            controller.setValue(null);
        }
    },
    
    /**
     * Open the link.
     * @param {Ext.form.field.Text} input The input text.
     * @param {Ext.event.Event} e The event object.
     */
    openLink: function()
    {
    	var node = this._currentNode;
    	if (node != null && node.getAttribute("href") != '')
    	{
    		if (node.href.indexOf("javascript") == 0)
    		{
    			window.location.href = node.href;
    		}
    		else
    		{
    			window.open(node.href);
    		}
    	}
    },
	
	// ---------------------------------------- //
	//                 TITLE                    //
	// ---------------------------------------- //
	
    /**
     * Set 'title' attribute to current &lt;a&gt; node
     * @param {Ext.form.field.Text} input The input text
     */
    setTitleOnBlur: function(input)
    {
    	var link = this._currentNode;
    	var inputValue = input.getValue();
    	
    	if (this._currentNode && link.getAttribute('title') != inputValue)
		{
    		 this.setTitle(inputValue);
		}
    },
    
    /**
     * Set 'title' attribute to current &lt;a&gt; node when pressing ENTER or ESC key.
     * @param {Ext.form.field.Text} input The input text.
     * @param {Ext.event.Event} e The event object.
     */
    setTitleOnSpecialKey: function(input, e)
    {
        if (e.getKey() == e.ENTER)
        {
            e.preventDefault();
            e.stopPropagation();
            this.setTitle(input.getValue());
            // FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
            tinyMCE.activeEditor.focus();
        }
        else if (e.getKey() == e.ESC)
        {
            e.preventDefault();
            e.stopPropagation();
            input.setValue(this._getTitle());
            // FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
            tinyMCE.activeEditor.focus();
        }
    },
    
    /**
     * Set 'title' attribute to current &lt;a&gt; node
     * @param {String} value The value.
     */
    setTitle: function(value)
    {
        var link = this._currentNode;
        if (link != null)
        {
            if (value == '')
            {
                link.removeAttribute('title');
            }
            else
            {
                link.setAttribute('title', value);
            }
            tinyMCE.activeEditor.execCommand('mceAddUndoLevel');
        }
    },
    
    /**
     * Enable/disable controller and set input value according to the selected link.
     * @param {Ametys.ribbon.element.ui.FieldController} controller The controller.
     * @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
     * @param {HTMLElement} node The current selected node. Can be null.
     */
    titleSelectionListener: function(controller, field, node)
    {
        if (node)
        {
            controller.setValue(this._getTitle(node));
        }
        else
        {
            controller.setValue('');
        }
        
        this._currentNode = node;
    },
    
    /**
     * Get the 'title' attribute of a &lt;a&gt; node
     * @param {HTMLElement} node The &lt;a&gt; node. Can be null to retrieve &lt;a&gt; node from cursor current position.
     * @return {String} The title attribute.
     * @private
     */
    _getTitle: function(node)
    {
        return node.getAttribute('title') || '';
    },
    
    // ---------------------------------------- //
    //           OPEN IN NEW WINDOW             //
    // ---------------------------------------- //
    
    /**
     * Set the target field.
     * @param {Ext.form.field.Checkbox} input The input text.
     */
    setOpenNewWindow: function(input)
    {
		var newValue = input.getValue();
		if (newValue != this._getOpenInNewWindow())
        {
            this._currentNode.setAttribute('target', newValue ? '_blank' : '');
            // FIXME "tinyMCE.activeEditor" a better method is to use the field.getEditor()
            tinyMCE.activeEditor.execCommand('mceAddUndoLevel');
        }
		tinyMCE.activeEditor.focus();
    },
    
	/**
	 * @private
	 * Is the link open in new window option activated ?
	 */
	_getOpenInNewWindow: function()
	{
		if (this._currentnode)
		{
			return this._currentnode.getAttribute("target") != null && this._currentnode.getAttribute("target") == "_blank"; 
		}
	},
    
    /**
     * Enable/disable controller and set input value according to the selected link.
     * @param {Ametys.ribbon.element.ui.FieldController} controller The controller.
     * @param {Ametys.cms.form.widget.RichText} field The current field. Can be null
     * @param {HTMLElement} node The current selected node. Can be null.
     */
    openNewWindowSelectionListener: function(controller, field, node)
    {
        if (!node || node.getAttribute('data-ametys-type') == 'mail')
        {
            controller.disable();
        }
        else
        {
            var target = node.getAttribute('target');
            controller.setValue(target != null && target == '_blank');
        }
    }
});