Ext.namespace('Zarafa.core.ui');

/**
 * @class Zarafa.core.ui.MainContentTabPanel
 * @extends Ext.TabPanel
 * @xtype zarafa.maincontenttabpanel
 * This subclass is used in the main content area, and contains the ContextContainer and dialogs that the user opens
 * Initialized in MainViewport.CreateContentContainer
 */
Zarafa.core.ui.MainContentTabPanel = Ext.extend(Ext.TabPanel, {

	/**
	 * The list of opened tab. It contains the list with the entryid and tab id.
	 * @property
	 * @type Ext.util.MixedCollection
	 * @private
	 */
	openedTabs : new Ext.util.MixedCollection(),

	/**
	 * Overriden to modify the tab depending on whether the record has been edited or not
	 * This method is called when a contained component fires the 'titlechange' event
	 * @param {Component} item
	 * @param {String} title
	 * @override
	 * @private
	 */
	onItemTitleChanged : function(item, title, oldTitle)
	{
		var el = this.getTabEl(item);
		if (el) {
			// now elide title if it exceeds 20 character length
			var tab = Ext.get(el).child('.x-tab-strip-text', true);

			// Change tooltip, and give full title in tab tool tip
			tab.qtip = title;

			tab.innerHTML = Ext.util.Format.htmlEncodeElide(title, 20, 0);
		}
	},

	/**
	 * This method is called when a contained component fires the 'iconchange' event
	 * @param {Component} item
	 * @param {String} iconCls icon class to apply
	 * @param {String} oldCls The previous icon class
	 * @private
	 */
	onItemIconChanged : function(item, iconCls, oldCls)
	{
		var tabEl = this.getTabEl(item);
		if (!Ext.isEmpty(tabEl)) {
			// removeClass only works when the CSS classes have been split
			// into an array, as it will not do it manually. For addClass,
			// we do not have this restriction.
			if (oldCls) {
				oldCls = oldCls.split(' ');
			}

			var tabText = Ext.get(tabEl).child('.x-tab-strip-text');
			if (iconCls) {
				tabText.addClass('x-tab-strip-icon');
				tabText.replaceClass(oldCls, iconCls);
			} else {
				tabText.removeClass('x-tab-strip-icon');
				tabText.removeClass(oldCls);
			}
		}
	},

	/**
	 * This method is called when contained component fires the 'userupdaterecord' event
	 * @param {Component} item The item which fired the event
	 * @param {Ext.data.Record} record Which was updated by the user
	 * @param {Boolean} changed True if the item has been changed by the user
	 * @private
	 */
	onItemUserUpdateRecord : function(item, record, changed)
	{
		var el = this.getTabEl(item);
		if (el) {
			var tab = Ext.get(el).child('.x-tab-strip-text');
			if (record.phantom || changed) {
				tab.addClass('zarafa-tab-edited');
			} else {
				tab.removeClass('zarafa-tab-edited');
			}
		}

		// If record get saved then add record id
		if (!record.phantom && !this.getOpenedTab(record)) {
			this.registeredOpenTab(record, item.getId());
		}
	},

	/**
	 * Overriden in order to listen to close event of child component
	 * @param {Component} item
	 * @param {Number} index
	 * @override
	 * @private
	 */
	initTab : function(item, index)
	{
		var title = item.title;
		if(!Ext.isEmpty(title)) {
			// provide a tooltip for tab titles
			item.tabTip = title;
			// now we can shorten the length of title if its exceeding 20 characters
			item.title = Ext.util.Format.htmlEncodeElide(title, 20, 0);
		}

		Zarafa.core.ui.MainContentTabPanel.superclass.initTab.call(this, item, index);

		item.on({
			scope : this,
			render : this.applyTooltip,
			iconchange : this.onItemIconChanged,
			userupdaterecord : this.onItemUserUpdateRecord,
			close : this.onTabClose
		});
	},

	/**
	 * This will apply tooltip on close button ('X') of {@link Ext.Panel Panel}.
	 * @param {Component} item.
	 */
	applyTooltip : function(item)
	{
		var el = item.tabEl;
		var closeTab = Ext.get(el).child('.x-tab-strip-close', true);
		if(closeTab) {
			closeTab.qtip = _('Close') + ' (Ctrl + Alt + W)';
		}
	},

	/**
	 * Handler for closing a tab when a child component has fired its close event
	 * For instance when a mail is sent, the MailCreateContentPanel needs to be closed
	 * @param {Component} tab
	 */
	onTabClose : function(tab)
	{
		if (this.fireEvent('beforeclose', tab)!==false) {
			this.remove(tab);
			this.openedTabs = this.openedTabs.filterBy(function (item) {
				return item !== tab.getId();
			});
			this.fireEvent('close', tab);
		}
	},

	/**
	 * handler for the '+' button in the tab strip
	 * adds a new item of type depending on current context
	 * @param {Ext.EventObjectImpl} e Event object
	 * @param {Element} t Event target
	 * @param {Object} o Configuration object
	 */
	onTabAddClick : function(e, t, o)
	{
		var model = container.getCurrentContext().getModel();

		if(model){

			if(model.createRecord === Ext.emptyFn) {
				//if unable to create record from the current context model, try to get the model based on the scope of the mainToolbar button
				var button = container.getMainPanel().mainToolbar.newButton;
				model = button.scope.model;
			}

			var record = model.createRecord();
			if (!record) {
				//if unable to create record from the current context model, invoke the handler of the first item in the 'new' menu
				var button = container.getMainPanel().mainToolbar.newButton;
				button.handler.call(button.scope);
				return;
			} else {
				// This will always use tab layer only, no matter what layer is configured in settings
				Zarafa.core.data.UIFactory.openCreateRecord(record, {layerType : 'tab'});
			}
		}
	},

	/**
	 * Overriden in order to add the '+' button to the edge of the tabstrip
	 * @param {Ext.Element} ct Container in which the panel is created
	 * @param {Element} position Element at which the panel is created (relative to its position)
	 * @override
	 */
	onRender : function(ct, position)
	{
		Zarafa.core.ui.MainContentTabPanel.superclass.onRender.call(this, ct, position);

		// insert add button into the edge element
		var edge = this.edge.update('<span id="zarafa-mainpanel-addtabbutton" class=\'x-tab-add\'></span>');
		this.mon(edge, 'click', this.onTabAddClick, this);

		// set tooltip on add button
		var addBtn = edge.child('.x-tab-add', true);
		addBtn.qtip = _('New item') + ' (Ctrl + Alt + N)';
	},

	/**
	 * Overriden in order to call close() on the item, instead of removing it immediately
	 * This allows the contained panel to fire a confirmation dialog
	 * @param {Ext.EventObjectImpl} e Event
	 * @private
	 * @override
	 */
	onStripMouseDown : function(e)
	{
		if (e.button !== 0) {
			return;
		}


		var target = this.findTargets(e);
		if (target.close) {
			target.item.close();
			return;
		}
		if (target.item && target.item != this.activeTab) {
			this.setActiveTab(target.item);
		}
	},

	/**
	 * Overriden so that '+' sign for adding tabs remains visible when there are scroll buttons
	 * @private
	 * @override
	 */
	getScrollWidth : function()
	{
		return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos() + this.edge.getWidth();
	},

	/**
	 * Fires before Ext.Component is added or inserted into the Zarafa.core.ui.MainContentTabPanel
	 * It will verify if the record is already opened in tab. If yes then moved focus on that tab,
	 * Otherwise add tab id into openedTabs.
	 * @param {Component} tab
	 */
	onBeforeAdd: function (tab)
	{
		if (tab.name === "main.content" || !tab.dialog) {
			return;
		}

		var record = tab.dialog.record;
		if (!Ext.isEmpty(record) && !Ext.isEmpty(record.get("entryid"))) {
			var openedTab = this.getOpenedTab(record);
			if (openedTab) {
				container.getTabPanel().setActiveTab(openedTab);
				return false;
			} else {
				this.registeredOpenTab(record,tab.getId());
			}
		}
	},

	/**
	 * Register a newly created tab with the {@link #openedTabs}.
	 * If record is {@link Zarafa.core.data.AppointmentRecord AppointmentRecord} recurring occurence appointment then
	 * append basedate with entryid.
	 *
	 * @param {Ext.data.Record} record
	 * @param {String} tabId id of tab component.
	 */
	registeredOpenTab: function (record, tabId)
	{
		var entryid = record.get("entryid");
		if (!Ext.isEmpty(record.get("basedate"))) {
			entryid += "_" + record.get('basedate').getTime();
		}
		this.openedTabs.add(entryid, tabId);
	},

	/**
	 * Function which is use to find tab id of given record.
	 * @param {Zarafa.core.data.MAPIRecord} record
	 * @returns {String | Boolean} Tab id if record is already opened, false otherwise.
	 */
	getOpenedTab: function (record)
	{
		return this.openedTabs.find(function (key, item) {
			if (!Ext.isEmpty(record.get("basedate"))) {
				if (item.indexOf(record.get("basedate").getTime()) > -1) {
					item = item.split("_")[0];
				} else {
					item = false;
				}
			}
			if (Zarafa.core.EntryId.compareEntryIds(item, record.get("entryid"))) {
				return true;
			}
		});
	}
});

Ext.reg('zarafa.maincontenttabpanel', Zarafa.core.ui.MainContentTabPanel);
