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

/**
 * @class Zarafa.calendar.ui.TextEditView
 * @extends Zarafa.core.ui.View
 *
 * The TextEditView shows a text area for a given date range. It is shown automatically when a user selects a
 * date range on the calendar and starts typing. It allows for convenient creation of appointments.
 * <p>
 * Two TextArea HTML components are used, one in the header and one on the body. Only one of them is visible depending
 * on the date range given (>=24 hour appointments are laid out in the header).
 *
 */
Zarafa.calendar.ui.TextEditView = Ext.extend(Zarafa.core.ui.View, {
	/**
	 * Date range.
	 * @property
	 * @type Zarafa.core.DateRange
	 */
	dateRange : undefined,

	/**
	 * @cfg {Number} minimumHeight The minimum height for this view.
	 */
	minimumHeight : 20,

	/**
	 * @cfg {String} inputText The text which was entered into the view.
	 */
	inputText : '',

	/**
	 * @constructor
	 * @param {Object} config configuration object
	 */
	constructor : function(config)
	{
		config = config || {};

		Ext.applyIf(config, {
			baseCls: 'zarafa-calendar',
			itemCls: 'textedit'
		});

		this.addEvents(
			/**
			 * Fires when the user is done entering text.
			 * @event textentered
			 * @param {Zarafa.calendar.ui.TextEditView} view source view.
			 * @param {String} text The text that was entered.
			 */
			'textentered',
			/**
			 * Fires when the user cancelled entering text by pressing escape or removing focus from the text area.
			 * @param {Zarafa.calendar.ui.TextEditView} view source view.
			 * @event cancelled
			 */
			'cancelled'
		);

		Zarafa.calendar.ui.TextEditView.superclass.constructor.call(this, config);
	},

	/**
	 * Sets date range. This method does not auto-update.
	 * @param {Zarafa.core.DateRange} dateRange
	 */
	setDateRange : function(dateRange)
	{
		this.dateRange = dateRange;
	},

	/**
	 * Returns the current date range.
	 * @return {Zarafa.core.DateRange} dateRange
	 */
	getDateRange : function()
	{
		return this.dateRange;
	},

	/**
	 * @return {Boolean} true iff the text edit area is visible.
	 */
	isVisible : function()
	{
		return this.visible;
	},

	/**
	 * Renders the view.
	 * @param {Ext.Element} container The Ext.Element into which the view must be rendered.
	 */
	render : function(container)
	{
		this.create('textarea', this.parentView.getCalendarBody(), 'body', this.getClassName('body'));
		this.create('textarea', this.parentView.getCalendarHeader(), 'header', this.getClassName('header'));
		this.header.setSize(2,2);
		this.mon(this.body, 'keypress', this.onKeyPress, this);
		this.mon(this.body, 'keydown', this.onKeyPress, this);
		this.mon(this.body, 'blur', this.onBlur, this);
		this.mon(this.body, 'keyup', this.onKeyUp, this);
		this.mon(this.header, 'keypress', this.onKeyPress, this);
		this.mon(this.header, 'keydown', this.onKeyPress, this);
		this.mon(this.header, 'blur', this.onBlur, this);
		this.mon(this.header, 'keyup', this.onKeyUp, this);

		Zarafa.calendar.ui.TextEditView.superclass.render.call(this, container);

		this.hide();
	},

	/**
	 * Sets the visibility of a given set elements. This function is used instead of ExtJS's Element.show()/hide() because
	 * for some reason Chrome seemed to crash on hide(). Freaky.
	 * @param {Ext.Element[]} elements elements to show or hide.
	 * @param {Boolean} visible whether to show or hide the elements.
	 * @private
	 */
	makeElementsVisible : function(elements, visible)
	{
		Ext.each(elements, function(element) {
			element.setVisible(visible);
		});
	},

	/**
	 * Hides the view.
	 */
	hide : function()
	{
		if (!this.rendered) {
			return;
		}

		this.makeElementsVisible([this.body, this.header], false);

		this.visible = false;
	},

	/**
	 * Makes the view visible. The proper order is to first set the date range, then call show() which will
	 * automatically lay out the appropriate TextArea component.
	 */
	show : function()
	{
		if (!this.rendered) {
			return;
		}

		this.visible = true;
		this.layout();

	},

	/**
	 * Handles the keypress event.
	 * @param {Ext.EventObject} event ExtJS event object.
	 * @private
	 */
	onKeyPress : function(event)
	{

		// Escape pressed. Blur.
		if (event.keyCode == event.ESC) {
			this.hide();
		}

		// Enter pressed. Fire 'textentered' event.
		if (event.keyCode == event.RETURN) {
			var text = event.browserEvent.target.value;
			event.browserEvent.target.value = '';
			this.inputText = '';
			this.hide();

			this.fireEvent('textentered', this, text);
		}

	},

	/**
	 * Handles the keyup event.
	 * Function will get and store input text.
	 * @param {Ext.EventObject} event ExtJS event object.
	 * @private
	 */
	onKeyUp: function (event)
	{
		if (event.keyCode !== event.RETURN) {
			this.inputText = event.browserEvent.target.value;
		}
	},

	/**
	 * Handles a blur event (lost focus) from a text area. The view is hidden and a 'cancel' event is fired.
	 * @param {Ext.EventObject} event ExtJS event object.
	 * @private
	 */
	onBlur : function(event)
	{
		var isHeaderRange = this.parentView.isHeaderRange(this.getDateRange());

		if ( (isHeaderRange && event.target==this.header.dom) || (!isHeaderRange && event.target == this.body.dom)) {
			this.hide();
			this.fireEvent('cancelled', this);
		}
	},

	/**
	 * Lays out the body of the view.
	 * @private
	 */
	layoutInBody : function()
	{
		this.makeElementsVisible(this.header, false);

		// get an array of bounds (left, right, top, bottom) objects to represent the range on the calendar body
		var bounds = this.parentView.dateRangeToBodyBounds(this.dateRange);

		if (bounds.length === 0) {
			this.makeElementsVisible(this.body, false);
		} else {
			this.makeElementsVisible(this.body, true);
			this.body.setLeftTop(bounds[0].left, bounds[0].top);
			this.body.setSize(bounds[0].right - bounds[0].left, bounds[0].bottom - bounds[0].top);
		}

	},

	/**
	 * Lays out the header of the view.
	 * @private
	 */
	layoutInHeader : function()
	{
		this.makeElementsVisible(this.body, false);

		// get an array of bounds (left, right, top, bottom) objects to represent the range on the calendar body
		var bounds = this.parentView.dateRangeToHeaderBounds(this.dateRange, this.slot);

		this.makeElementsVisible(this.header, true);
		this.header.setLeftTop(bounds.left, bounds.top);
		this.header.setSize(bounds.right - bounds.left, this.minimumHeight);
	},

	/**
	 * Lays out the view.
	 * @protected
	 */
	onLayout : function()
	{
		if (!this.rendered) {
			return;
		}

		if (this.visible) {
			if (this.parentView.isHeaderRange(this.getDateRange())) {
				this.layoutInHeader();
			} else {
				this.layoutInBody();
			}
		} else {
			this.makeElementsVisible([this.body, this.header], false);

			// If input text is not empty then create the appointment
			if (!Ext.isEmpty(this.inputText)) {
				var text = this.inputText;
				this.inputText = '';
				this.fireEvent('textentered', this, text);
			}
		}

		Zarafa.calendar.ui.TextEditView.superclass.onLayout.call(this);
	},

	/**
	 * Makes the view visible (set the date range first) and sets the appropriate text area control selected - focus is moved
	 * to the text area and the user can immediately start typing.
	 */
	select : function()
	{
		if (!this.rendered) {
			return;
		}

		this.show();

		if (this.parentView.isHeaderRange(this.getDateRange())) {
			this.header.dom.select();
		} else {
			this.body.dom.select();
		}
	}
});