Ext.namespace('Zarafa.common.freebusy.ui');

/**
 * @class Zarafa.common.freebusy.ui.FreebusyPanel
 * @extends Ext.Panel
 * @xtype zarafa.freebusypanel
 */
Zarafa.common.freebusy.ui.FreebusyPanel = Ext.extend(Ext.Panel, {
	/**
	 * @cfg {Zarafa.common.freebusy.data.FreebusyBlockStore} blockStore
	 * The {@link Ext.data.Store} object that handles the freebusy blocks displayed on the timeline.
	 */
	blockStore: null,
	/**
	 * @cfg {Ext.data.Store} userStore
	 * The {@link Ext.data.Store} object that handles the list of users loaded. It can be a normal
	 * store, but it is preferably an {@link  Zarafa.core.data.IPMRecipientStore}.
	 */
	userStore: null,
	/**
	 * @cfg {Zarafa.common.freebusy.data.FreebusyModel} model
	 * The model that keeps track of the userStore, dates, etc.
	 */
	model: null,
	/**
	 * @cfg {Object} userlistConfig The configuration object which will be applied
	 * to the {@link Zarafa.common.freebusy.ui.UserListView UserListView} object.
	 */
	userlistConfig: null,
	/**
	 * @cfg {Object} timelineConfig The configuration object which will be applied
	 * to the {@link Zarafa.common.freebusy.ui.TimelineView TimelineView} object.
	 */
	timelineConfig: null,
	/**
	 * @cfg {Object} suggestionConfig The configuration object which will be applied
	 * to the {@link Zarafa.common.freebusy.ui.SuggestionListView SuggestionListView} object.
	 */
	suggestionConfig: null,
	/**
	 * @cfg {Object} legendaConfig The configuration object which will be applied
	 * to the {@link Ext.Panel legendaView} object.
	 */
	legendaConfig: null,
	/**
	 * @cfg {Boolean} showUserList
	 * When set to true it will show the userlist to the left. When set to false it will hide it
	 * (defaults to true).
	 */
	showUserList: true,
	/**
	 * @cfg {Boolean} showSuggestionList
	 * When set to true it will show the Suggestionlist to the left. When set to false it will hide it
	 * (defaults to true).
	 */
	showSuggestionList : true,
	/**
	 * @cfg {Boolean} editable
	 * When set to false it will make the userlist non-editable (defaults to true).
	 */
	editable: true,
	/**
	 * @cfg {Boolean} showLegenda
	 * When set to true it will show the legenda at the bottom. When set to false it will hide it
	 * (defaults to true).
	 */
	showLegenda: true,
	/**
	 * @cfg {Number} headerHeight
	 * Height of the header that will be set for the {@link Zarafa.common.freebusy.ui.UserlistView} and the
	 * {@link Zarafa.common.freebusy.ui.TimelineView} (defaults to 50).
	 */
//	headerHeight: 50,
	// Private
	// Height of inputfield that will be shown in the {@link Zarafa.common.freebusy.ui.UserlistView}.
	inputfieldHeight: 20,
	/**
	 * @cfg {Boolean} initialScrollToCurrentDay
	 * When set to true it will scroll to the current day or the selected period. This is done after
	 * the initial laying out (Defaults to true).
	 */
	initialScrollToCurrentDay: true,
	// Private
	// The afterlayout event triggers the scrolling of the timeline to the current day or selection.
	// This flag indicates whether we should react the afterlayout event or whether this has already
	// happened.
	initialScrollDone: false,

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

		var modelConfig = config.modelConfig || {};
		Ext.applyIf(modelConfig, {
			userStore: config.userStore,
			blockStore: config.blockStore
		});
		var model = new Zarafa.common.freebusy.data.FreebusyModel(modelConfig);

		Ext.applyIf(config, {
			layout: 'border',
			border: true,

			blockStore: model.getBlockStore(),
			userStore: model.getUserStore(),
			model: model,

			userlistConfig: {},
			timelineConfig: {},
			suggestionConfig: {},
			legendaConfig: {}
		});

		Zarafa.common.freebusy.ui.FreebusyPanel.superclass.constructor.call(this, config);

		this.add([
			this.createUserListView(),
			this.createSuggestionView(),
			this.createTimelineView(),
			this.createLegendaView()
		]);

		this.initFreebusyEvents();
	},

	/**
	 * This will create the listview panel containing all the users for
	 * which the freebusy should be shown.
	 * @return {Object} Configuration object for the user listview
	 * @private
	 */
	createUserListView : function()
	{
		return {
			xtype: 'panel',
			ref: 'userListView',
			region: 'west',
			layout: 'fit',
			title: _('Select attendees'),
			hidden: (!this.showUserList),
			cls: 'x-freebusy-userlist',
			footer: true,
			footerCfg: {
				tag: 'div',
				cls: 'x-panel-footer'
			},
			border: true,
			width: 200,
			collapsible: true,
			split: true,
			items: [Ext.applyIf(this.userlistConfig, {
				xtype: 'zarafa.freebusyuserlistview',

				model: this.model,

				inputFieldHeight: (this.editable) ? this.inputfieldHeight : 0,
				editable: this.editable
			})]
		};
	},

	/**
	 * This will create the suggestion listview which contains all possible
	 * times for an appointment for the selected users on a given day.
	 * @return {Object} Configuration object for the suggestion listview
	 * @private
	 */
	createSuggestionView : function()
	{
		return {
			xtype: 'panel',
			ref: 'suggestionListView',
			region: 'east',
			layout: 'fit',
			title: _('Suggested Times'),
			hidden: (!this.showSuggestionList),
			cls: 'zarafa-freebusy-suggestionlist',
			footer: true,
			footerCfg: {
				tag: 'div',
				cls: 'x-panel-footer'
			},
			border: true,
			width: 200,
			collapsible: true,
			split: true,
			items: [Ext.applyIf(this.suggestionConfig, {
				xtype: 'zarafa.freebusysuggestionlistpanel',

				model: this.model,

				listeners: {
					select: this.onSelectSuggestion,
					dateselect: this.onSuggestionDateSelect,
					scope: this
				}
			})]
		};
	},

	/**
	 * This will create the timeline panel which contains all the freebusy blocks
	 * for each user which has been selected.
	 * @return {Object} Configuration object for the timelineview
	 * @private
	 */
	createTimelineView : function()
	{
		return Ext.applyIf(this.timelineConfig, {
			xtype: 'zarafa.freebusytimelineview',
			ref: 'timelineView',
			region: 'center',
			blockStore: this.blockStore,
			model: this.model,
			selector: new Zarafa.common.freebusy.data.TimelineSelector(),
			extraBodyHeight: (this.editable) ? this.inputfieldHeight : 0,
			// TODO: Make this configurable and toggable
			hideNonWorkingHours: true,
			listeners: {
				bodyscroll : this.onTimelineScroll,
				scope: this
			}
		});
	},

	/**
	 * This will create the legenda panel which contains all the possible
	 * block colors which will be used in the timelineview.
	 * @return {Object} configuration object for the legenda
	 * @private
	 */
	createLegendaView : function()
	{
		return Ext.applyIf(this.legendaConfig, {
			xtype: 'container',
			region: 'south',
			border: false,
			layout: 'hbox',
			hidden: (!this.showLegenda),
			autoHeight: true,
			cls: 'x-freebusy-timeline-container x-freebusy-legenda',
			items: [{
				xtype: 'container',
				cls: 'x-freebusy-timeline-block-busy',
				width: 24,
				height: 24
			},{
				xtype: 'displayfield',
				value: _('Busy'),
				hideLabel : true,
				autoWidth: true
			},{
				xtype: 'container',
				cls: 'x-freebusy-timeline-block-tentative',
				width: 24,
				height: 24
			},{
				xtype: 'displayfield',
				value: _('Tentative'),
				hideLabel : true,
				autoWidth: true
			},{
				xtype: 'container',
				cls: 'x-freebusy-timeline-block-outofoffice',
				width: 24,
				height: 24
			},{
				xtype: 'displayfield',
				value: _('Out of Office'),
				hideLabel : true,
				autoWidth: true
			},{
				xtype: 'container',
				cls: 'x-freebusy-timeline-block-blur',
				width: 24,
				height: 24
			},{
				xtype: 'displayfield',
				value: _('No Information'),
				hideLabel : true,
				autoWidth: true
			}]
		});
	},

	/**
	 * Initialize freebusy events
	 * @private
	 */
	initFreebusyEvents: function()
	{
		// Register to afterlayout to support the timeline in scrolling to the current day
		this.on('afterlayout', this.onAfterLayout, this);
	},

	/**
	 * Returns the model.
	 * @return {Zarafa.common.freebusy.data.FreebusyModel} Model
	 */
	getModel: function()
	{
		return this.model;
	},

	/**
	 * Change the {@link #editable} field on this panel
	 * @param {Boolean} value The new editable status
	 */
	setEditable : function(value)
	{
		if (this.editable !== value) {
			this.editable = value;
			this.userListView.get(0).setEditable(value);
		}
	},

	/**
	 * Is called when the layouting is done and the sizes are calculated. When the timeline needs to
	 * be scrolled to the current day or selection, this listener triggers the scrolling. It looks
	 * for the first usable afterlayout event and the ones after that will not trigger any scrolling
	 * anymore. The first usable event is the one where the container has a width larger than zero.
	 * @param {Ext.Container} container Container
	 * @private
	 */
	onAfterLayout: function(container)
	{
		// Calculate the desired header size, we have the configured header size, but we need
		// to substract any padding/borders and margins which are applied to the header.
		if (this.userListView) {
			var height = this.headerHeight;

			height -= this.userListView.header.getMargins('tb');
			height -= this.userListView.header.getBorderWidth('tb');
			height -= this.userListView.header.getPadding('tb');

			this.userListView.header.setStyle('height', height + 'px');

			// Ext.getScrollBarWidth() is always off by 2 pixels, this is a hardcoded
			// thing, so we can fix it hardcoded...
			this.userListView.footer.setStyle('height', (Ext.getScrollBarWidth() - 2) + 'px');
		}
		if (this.suggestionListView) {
			var height = this.headerHeight;

			height -= this.userListView.header.getMargins('tb');
			height -= this.userListView.header.getBorderWidth('tb');
			height -= this.userListView.header.getPadding('tb');

			this.suggestionListView.header.setStyle('height', height + 'px');
			// Ext.getScrollBarWidth() is always off by 2 pixels, this is a hardcoded
			// thing, so we can fix it hardcoded...
			this.suggestionListView.footer.setStyle('height', (Ext.getScrollBarWidth() - 2) + 'px');
		}

		if (this.initialScrollToCurrentDay) {
			/**
			 * We only need to scroll to the current day or selection once at startup. We have to
			 * look for the first afterlayout event with a container that has a width larger than 0.
			 */
			 // @TODO every time on layout we must need to scroll timeline to current selection as "scroll" event is not working properly in IE.
			if (!Ext.isIE && (this.initialScrollDone || this.timelineView.getWidth() === 0)) {
				return;
			} else {
				this.initialScrollDone = true;
			}

			this.scrollTimelineToSelection();
		}
	},

	/**
	 * Scroll the TimelineView to the current Selector date, or to
	 * the current date if no selector is available.
	 */
	scrollTimelineToSelection : function()
	{
		if (this.timelineView.selector) {
			this.timelineView.selector.scrollTimelineToSelection();
		} else {
			this.timelineView.scrollDateIntoView(new Date());
		}
	},

	/**
	 * Scroll the TimelineView to the provided date argument.
	 * @param {Date} date Date object
	 */
	scrollTimelineToDate : function(date)
	{
		this.timelineView.scrollDateIntoView(date);
	},

	/**
	 * Used to syncronize the scrolling height of the timeline view with the user list
	 * @param {Object} scrollPos Scroll position
	 * @private
	 */
	onTimelineScroll: function(scrollPos)
	{
		this.userListView.body.scrollTo('top', scrollPos.top);
	},

	/**
	 * Fired when the user clicks on a suggestion from the SuggestionPanel.
	 * This will update the Selector DateRange to match the suggestion.
	 * @param {Zarafa.common.freebusy.ui.SuggestionListPanel} panel The panel which raised the event
	 * @param {Zarafa.common.freebusy.data.FreebusyBlockRecord} record The selected suggestion
	 * @private
	 */
	onSelectSuggestion : function(panel, record)
	{
		var start = record.get('start') * 1000;
		var end = record.get('end') * 1000;

		this.getModel().getSelectorRange().setTime(start, end);
	},

	/**
	 * Called when the {@link Zarafa.common.freebusy.ui.SuggestionListPanel SuggestionListPanel} fires
	 * the {@link Zarafa.common.freebusy.ui.SuggestionListPanel#dateselect dateselect} event.
	 * @param {Zarafa.common.freebusy.ui.SuggestionListPanel} this This panel
	 * @param {Date} date The selected date
	 * @private
	 */
	onSuggestionDateSelect: function(suggestionListPanel, date)
	{
		this.scrollTimelineToDate(date);
	}

});

Ext.reg('zarafa.freebusypanel',Zarafa.common.freebusy.ui.FreebusyPanel);