/**
 * Represents an individual tab within a Stack's header
 *
 * @param {lm.controls.Header} header
 * @param {lm.items.AbstractContentItem} contentItem
 *
 * @constructor
 */
lm.controls.Tab = function (header, contentItem) {
	this.header = header;
	this.contentItem = contentItem;
	this.element = $(lm.controls.Tab._template);
	this.titleElement = this.element.find('.lm_title');
	this.closeElement = this.element.find('.lm_close_tab');
	this.closeElement[contentItem.config.isClosable ? 'show' : 'hide']();
	this.isActive = false;

	this.setTitle(contentItem.config.title);
	this.contentItem.on('titleChanged', this.setTitle, this);

	this._layoutManager = this.contentItem.layoutManager;

	if (
		this._layoutManager.config.settings.reorderEnabled === true &&
		contentItem.config.reorderEnabled === true
	) {
		this._dragListener = new lm.utils.DragListener(this.element);
		this._dragListener.on('dragStart', this._onDragStart, this);
		this.contentItem.on('destroy', this._dragListener.destroy, this._dragListener);
	}

	this._onTabClickFn = lm.utils.fnBind(this._onTabClick, this);
	this._onCloseClickFn = lm.utils.fnBind(this._onCloseClick, this);

	if (this._layoutManager.config.settings.mode === "workspace" && contentItem.config.noTabHeader) {
		this.element.hide();
	}

	this.element.on('mousedown touchstart', this._onTabClickFn);

	if (this.contentItem.config.isClosable) {
		this.closeElement.on('click touchstart', this._onCloseClickFn);
		this.closeElement.on('mousedown', this._onCloseMousedown);
	} else {
		this.closeElement.remove();
	}

	this.contentItem.tab = this;
	this.contentItem.emit('tab', this);
	this.contentItem.layoutManager.emit('tabCreated', this);

	if (this.contentItem.isComponent) {
		this.contentItem.container.tab = this;
		this.contentItem.container.emit('tab', this);
	}
};

/**
 * The tab's html template
 *
 * @type {String}
 */
lm.controls.Tab._template = '<li class="lm_tab"><i class="lm_left"></i>' +
	'<span class="lm_title"></span><div class="lm_close_tab"></div>' +
	'<i class="lm_right"></i></li>';

lm.utils.copy(lm.controls.Tab.prototype, {

	/**
	 * Sets the tab's title to the provided string and sets
	 * its title attribute to a pure text representation (without
	 * html tags) of the same string.
	 *
	 * @public
	 * @param {String} title can contain html
	 */
	setTitle: function (title) {
		this.element.attr('title', lm.utils.stripTags(title));
		this.titleElement.html(title);
	},

	onCloseClick: undefined,

	/**
	 * Sets this tab's active state. To programmatically
	 * switch tabs, use header.setActiveContentItem( item ) instead.
	 *
	 * @public
	 * @param {Boolean} isActive
	 */
	setActive: function (isActive) {
		if (isActive === this.isActive) {
			return;
		}
		this.isActive = isActive;

		if (isActive) {
			this.element.addClass('lm_active');
		} else {
			this.element.removeClass('lm_active');
		}
	},

	/**
	 * Destroys the tab
	 *
	 * @private
	 * @returns {void}
	 */
	_$destroy: function () {
		this.element.off('mousedown touchstart', this._onTabClickFn);
		this.closeElement.off('click touchstart', this._onCloseClickFn);
		if (this._dragListener) {
			this.contentItem.off('destroy', this._dragListener.destroy, this._dragListener);
			this._dragListener.off('dragStart', this._onDragStart);
			this._dragListener = null;
		}
		this.element.remove();
	},

	/**
	 * Callback for the DragListener
	 *
	 * @param   {Number} x The tabs absolute x position
	 * @param   {Number} y The tabs absolute y position
	 *
	 * @private
	 * @returns {void}
	 */
	_onDragStart: function (x, y) {
		if (this.contentItem.parent.isMaximized === true) {
			this.contentItem.parent.toggleMaximise();
		}
		const isWorkspaceLayout = this.contentItem.layoutManager.config.settings.mode === "workspace";
		const hasLessThanTwoTabs = this.contentItem.parent.header.tabs.length < 2;
		const isMissingWindowId = !this.contentItem.config.windowId && (this.contentItem.config.componentState && !this.contentItem.config.componentState.windowId);

		if (isWorkspaceLayout && hasLessThanTwoTabs) {
			return;
		}

		if (!isWorkspaceLayout && isMissingWindowId) {
			return;
		}

		if (this._layoutManager.config && this._layoutManager.config.workspacesOptions.allowExtract === false &&
			this.contentItem.config.workspacesConfig && this.contentItem.config.workspacesConfig.allowExtract !== true) {
			return;
		} else if (this.contentItem.config.workspacesConfig && this.contentItem.config.workspacesConfig.allowExtract === false) {
			return;
		}

		const newProxy = new lm.controls.DragProxy(
			x,
			y,
			this._dragListener,
			this._layoutManager,
			this.contentItem,
			this.header.parent
		);

		this._layoutManager._dragProxies.push(newProxy);
	},

	/**
	 * Callback when the tab is clicked
	 *
	 * @param {jQuery DOM event} event
	 *
	 * @private
	 * @returns {void}
	 */
	_onTabClick: function (event) {
		// left mouse button or tap
		if (event.button === 0 || event.type === 'touchstart') {
			var activeContentItem = this.header.parent.getActiveContentItem();
			if (this.contentItem !== activeContentItem) {
				this.header.parent.setActiveContentItem(this.contentItem);
			}

			// middle mouse button
		} else if (event.button === 1 && this.contentItem.config.isClosable) {
			this._onCloseClick(event);
		}
	},

	/**
	 * Callback when the tab's close button is
	 * clicked
	 *
	 * @param   {jQuery DOM event} event
	 *
	 * @private
	 * @returns {void}
	 */
	_onCloseClick: function (event) {
		this.contentItem.layoutManager.emit('tabCloseRequested', this);
		if (this.onCloseClick) {
			this.onCloseClick(event)
		}
	},


	/**
	 * Callback to capture tab close button mousedown
	 * to prevent tab from activating.
	 *
	 * @param (jQuery DOM event) event
	 *
	 * @private
	 * @returns {void}
	 */
	_onCloseMousedown: function (event) {
		event.stopPropagation();
	}
});
