/*
 *  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 tool is a tool for viewing or editing a content
 * @private
 */
Ext.define('Ametys.plugins.cms.content.tool.OldContentTool', {
	extend: "Ametys.tool.Tool",
	
	/**
	 * @property {String} _contentId The unique identifier of the content.
	 * @private
	 */
	
	/**
	 * @cfg {String} [metadata-set-name="main"] The name of metadata set of content to use for edition.
	 */
	/**
	 * @property _metadataSetName {String} The metadata set for edition. See #cfg-metadata-set-name.
	 */
	
	/**
	 * @cfg {String} [oldcontent-message-type="old-content"] The message type to send. Defaults to 'old-content'.
	 */
	/**
	 * @property _oldContentMessageType {String} The message type to send. See #cfg-oldcontent-message-type
	 */
	
	/**
	 * @private
	 * @property {Ext.ux.IFrame} _iframe The iframe object
	 */
	
	/**
	 * @private
	 * @property {Ext.Template} _tooltipDescriptionTpl The template used for tooltip description
	 */
	
	/**
	 * @private
	 * @property {Ext.Template} _hintTpl The template used for hint text
	 */
	
    /**
     * @private
     * @property {String} _baseUrl The url that the iframe should stay on
     */
    
	constructor: function (config)
	{
		this.callParent(arguments);
		
		this._hintTpl = new Ext.Template(
				'<div class="title">',
					'<span class="ametysicon-time51"></span>',
					"{title} ({{i18n PLUGINS_CMS_TOOL_CONTENT_INTRO_VERSION}}{version})",
				'</div>',
				'<div class="text">',
					"{{i18n PLUGINS_CMS_TOOL_CONTENT_INTRO_DESC1}}<br/>",
					"{{i18n PLUGINS_CMS_TOOL_CONTENT_INTRO_DESC2}}",
				'</div>'
		);
		
		this._tooltipDescriptionTpl = new Ext.Template(
				"<u>{{i18n PLUGINS_CMS_TOOL_CONTENT_TOOLTIP_VERSION}}</u> : ",
				"<b>v{version}</b><br/>",
				"<u>{{i18n PLUGINS_CMS_TOOL_CONTENT_TOOLTIP_AUTHOR}}</u> : ",
				"<b>{author}</b><br/>",
				"<u>{{i18n PLUGINS_CMS_TOOL_CONTENT_TOOLTIP_LASTMODIFICATION}}</u> : ",
				"<b>{lastModified}</b>"
		);
		
		this._oldContentMessageType = this.getInitialConfig('oldcontent-message-type')|| 'old-content';
	},
	
	createPanel: function ()
	{
		this._iframe = Ext.create("Ext.ux.IFrame", {}); 
		
		this._iframe.on ('load', this._onIframeLoad, this);
		
		return Ext.create('Ext.Panel', { 
			cls: 'oldcontenttool',
			border: false,
			layout: 'border',
			scrollable: false,
			
	   	 	items: [{
			   	 		region: 'north',
			   	 		xtype: 'component',
			   	 		cls: 'hint',
			   	 		html: ''
			   	 	},
			   	 	this._iframe
	   	 	]
		});
	},
	
	setParams: function (params)
	{
		this.callParent(arguments);
		
		this._contentId = params['id'];
		this._metadataSetName = params['metadata-set-name'] || 'main';
		this._contentVersion = params['contentVersion'];
		this._versionName = params['versionName'];
		
        // Register the tool on the history tool
        var toolId = this.getFactory().getId();
        var toolParams = this.getParams();

        Ametys.navhistory.HistoryDAO.addEntry({
            id: this.getId(),
            label: this.getTitle(),
            description: this.getDescription(),
            iconGlyph: this.getGlyphIcon(),
            iconSmall: this.getSmallIcon(),
            iconMedium: this.getMediumIcon(),
            iconLarge: this.getLargeIcon(),
            type: Ametys.navhistory.HistoryDAO.TOOL_TYPE,
            action: Ext.bind(Ametys.tool.ToolsManager.openTool, Ametys.tool.ToolsManager, [toolId, toolParams], false)
        });

		this.refresh();
	},
	
	refresh: function ()
	{
		this.showRefreshing();
		
		var wrappedUrl = this.getWrappedContentRevisionUrl ();
		
		this._iframe.load(Ametys.CONTEXT_PATH + wrappedUrl)
        this._baseUrl = Ametys.CONTEXT_PATH + wrappedUrl;
		
		this.showRefreshed();
		
		this._updateInfos();
	},
	
	/**
	 * Get the wrapped url for content old revision
	 * @returns {String} The wrapped url
	 */
	getWrappedContentRevisionUrl: function ()
	{
		var appParameters = Ametys.getAppParameters();
		
		var additionParams = '';
		Ext.Object.each(appParameters, function(key, value) {
			additionParams += '&' + key + '=' + encodeURIComponent(value);
		});
		
		return '/_wrapped-content/v_' +  this._contentVersion + '.html?contentId=' + this.getContentId() + additionParams;
	},
	
	/**
	 * Get the unique identifier of the content.
	 * @returns {String} The identifier of the content
	 */
	getContentId: function()
	{
		return this._contentId;
	},
	
	/**
	 * @private
	 * Listener called when the iframe is loaded.
	 * Protects the iframe by handling links of the internal frame by setting a onclick on every one
	 * @param {Ext.ux.IFrame} iframe The iframe
	 */
	_onIframeLoad: function (iframe)
	{
		if (window.event && window.event.srcElement.readyState && !/loaded|complete/.test(window.event.srcElement.readyState))
		{
			return;
		}
		
		Ametys.plugins.cms.content.tool.ContentTool.__URL_REGEXP.test(window.location.href);
		
		var win = this._iframe.getWin();
		
		var outside = false;
		try
		{
			win.location.href
		}
		catch (e)
		{
			outside = true;
		}
		
		if (outside || (win.location.href != 'about:blank' && win.location.href.indexOf(RegExp.$1 + this._baseUrl) != 0))
		{
			var outsideUrl = win.location.href;
			// Back to iframe base url
			win.location.href = this._baseUrl;
			// Open ouside url in a new window
			window.open(outsideUrl);
		}
		else
		{
			var links = win.document.getElementsByTagName("a");
			for (var a = 0; a < links.length; a++)
			{
				if (links[a].getAttribute("internal") == null && !links[a].onclick)
				{
					links[a].onclick = Ext.bind(this._handleLink, this, [links[a]], false);
				}
			}
		}
	},
	
	/**
	 * @private
	 * Lazy handling of links. Each times a link is clicked, check if we should open it in a window, open another tool...
	 * @param {HTMLElement} link The clicked link
	 */
	_handleLink: function(link)
	{
		var currentURI = this._iframe.getWin().location.href;
		
		var absHref = link.href;
		var relHref = null;
		if (/^(https?:\/\/[^\/]+)(\/.*)?/.test(absHref) && absHref.indexOf(RegExp.$1 + Ametys.CONTEXT_PATH) == 0)
		{
			relHref = absHref.substring(absHref.indexOf(RegExp.$1 + Ametys.CONTEXT_PATH) + (RegExp.$1 + Ametys.CONTEXT_PATH).length);
		}

		// Internal link
		if (absHref.indexOf(currentURI) == 0) return true;
		
		// JS Link
		if (absHref.indexOf("javascript:") == 0) return true;
		
		// Download link
		if (relHref != null && relHref.indexOf("/plugins/explorer/download/") == 0) return true;

		// Unknown link : open in a new window
		window.open(absHref);
		return false;
	},
	
	/**
	 * Update tool information
	 * @private
	 */
	_updateInfos: function()
	{
		Ametys.data.ServerComm.callMethod({
            role: "org.ametys.cms.repository.ContentDAO", 
            methodName: 'getContentDescription', 
            parameters: [ this.getContentId(), null],
            waitMessage: false,
            callback: {
                handler: this._updateInfosCb,
                scope: this,
                ignoreOnError: false
            }
        });
	},
	
	/**
	 * Callback function called after #_updateInfos is processed
     * @param {Object} data The server response
     * @param {String} data.title The title
     * @param {Object} data.lastContributor The last contributor object
     * @param {String} data.lastContributor.fullname The fullname of the last contributor
     * @param {String} data.lastModified The last modified date at 'd/m/Y, H:i' format
     * @param {String} data.iconGlyph A css class to set a glyph
     * @param {String} data.iconDecorator A css class to set a glyph decorator
     * @param {String} data.smallIcon The path to the small (16x16) icon. iconGlyph win if specified
     * @param {String} data.mediumIcon The path to the medium (32x32) icon. iconGlyph win if specified
     * @param {String} data.largeIcon The path to the large (48x48) icon. iconGlyph win if specified
     * @param {Object} args The callback parameters passed to the {@link Ametys.data.ServerComm#send} method
	 * @private
	 */
	_updateInfosCb: function (data, args)
	{
		var title = data.title + ' (v' + this._versionName + ')';
		this.setTitle(data.title);
		
		var values = {title: data.title, version: this._versionName, author: data.lastContributor.fullname, lastModified: Ext.util.Format.date(data.lastModified, 'd/m/Y, H:i')};
		var description = this._tooltipDescriptionTpl.applyTemplate (values);
		
		this.setDescription(description);
		
		// Set title, desc, and icons.
		if (data.iconGlyph)
        {
        	this.setGlyphIcon(data.iconGlyph);
            this.setIconDecorator(data.iconDecorator);
        }
        else
        {
        	this.setGlyphIcon(null);
        	this.setSmallIcon(data.smallIcon);
            this.setMediumIcon(data.mediumIcon);
            this.setLargeIcon(data.largeIcon);
        }
		
		this.getContentPanel().items.get(0).update(this._hintTpl.applyTemplate (values));
	},
	
	getMBSelectionInteraction: function() 
	{
		return Ametys.tool.Tool.MB_TYPE_ACTIVE;
	},
    
	sendCurrentSelection: function()
	{
		Ametys.cms.content.ContentDAO.getContent(this.getContentId(), Ext.bind(this._createContentTarget, this));
	},
	
	/**
	 * Creates and fires a event of selection on the message bus 
	 * @param {Ametys.cms.content.Content} content The concerned content
	 * @private
	 */
	_createContentTarget: function (content)
	{
		Ext.create("Ametys.message.Message", {
			type: Ametys.message.Message.SELECTION_CHANGED,
			
			targets: {
				id: this._oldContentMessageType,
				parameters: { contents: [content], 'version' : this._contentVersion, 'versionName' : this._versionName},
				
				subtargets: []
			}
		});
	}
	
});