Ext.namespace('Zarafa.calendar.ui');
/**
* @class Zarafa.calendar.ui.DatePicker
* @extends Ext.DatePicker
* @xtype zarafa.datepicker
* This overriden DatePicker takes the default calendar folder of the user, and displays days in which there are appointments differently.
* Currently the x-date-busy CSS class is applied to these days.
*/
Zarafa.calendar.ui.DatePicker = Ext.extend(Ext.DatePicker, {
	/**
	 * A {@link Zarafa.calendar.data.busytime.BusyTimeStore} store used for keeping appointments (containing only time and busy status)
	 * @property
	 * @type Zarafa.calendar.data.busytime.BusyTimeStore
	 * @private
	 */
	store: undefined,

	/**
	 * Beginning of the current month
	 * @property
	 * @type Date
	 * @private
	 */
	monthStart: undefined,

	/**
	 * End of the current month
	 * @property
	 * @type Date
	 * @private
	 */
	monthEnd: undefined,

	/**
	 * constructor
	 * @param {Object} config Configuration object
	 */
	constructor : function(config)
	{
		config = config || {};
		if(!config.store){
			config.store = new Zarafa.calendar.data.busytime.BusyTimeStore();
		}
		Zarafa.calendar.ui.DatePicker.superclass.constructor.call(this, config);

		// When the component is destroyed, we have to destroy the store
		this.on('destroy', this.store.destroy, this.store);

		// Set timer to change highlighted date in date picker
		// after date change during the session
		this.setNextDayTimer();
	},

	/**
	 * function called after the component has been rendered (right before the 'afterrender' event has fired)
	 * calls {@link #reloadStore}, which loads data from the store
	 * @private
	 */
	afterRender: function()
	{
		Zarafa.calendar.ui.DatePicker.superclass.afterRender.call(this);

		//attach event handlers
		//when store has finished loading, apply data from newly loaded appointments
		this.mon(this.store, 'load', this.onLoad, this);
	},

	/**
	 * used as a handler for the 'load' event. Invoked when the store has finished loading.
	 * @param {Zarafa.calendar.data.busytime.BusyTimeStore} store The store bound to this datepicker
	 * @param {Ext.data.Record[]} records an array of records loaded
	 * @param {Object} options The loading options specified
	 * @private
	 */
	onLoad: function(store, records, options)
	{
		this.clearCells();
		if (!this.settingIsSet()) {
			return false;
		}

		for (var i = 0, len = this.cells.elements.length; i < len; i++) {
			var cell = Ext.get(this.cells.elements[i]);
			var pickerDate = cell.dom.firstChild.dateValue;
			var foundAppt = false;

			for(var j = 0, len2 = records.length; j < len2; j++){
				var record = records[j];
				var storeDate = record.get('startdate').clearTime(true).getTime();
				if(pickerDate == storeDate && record.get('busystatus') != Zarafa.core.mapi.BusyStatus['FREE']){
					foundAppt=true;
					break;
				}
			}
			if (foundAppt) {
				cell.addClass('x-date-busy');
			} else {
				cell.removeClass('x-date-busy');
			}
		}
	},

	/**
	 * Event handler which is called when the component is made visible
	 * @private
	 */
	onShow : function()
	{
		this.reloadStore(this.cells.first().dom.firstChild.dateValue, this.cells.last().dom.firstChild.dateValue);
		Zarafa.calendar.ui.DatePicker.superclass.onShow.apply(this, arguments);
	},

	/**
	 * Event handler which is called when the component is hidden
	 * @private
	 */
	onHide : function()
	{
		this.store.cancelLoadRequests();
		Zarafa.calendar.ui.DatePicker.superclass.onHide.apply(this, arguments);
	},

	/**
	 * reload the store with date restrictions taken from the first and last cells of the table
	 * @param {Number} startDate beginning date for range in milliseconds
	 * @param {Number} dueDate final date for range in milliseconds
	 * @private
	 */
	reloadStore: function(startDate, dueDate)
	{
		var folder = container.getHierarchyStore().getDefaultFolder('calendar');
		if (folder) {
			this.monthStart = this.value.clone();
			this.monthStart.setDate(1);
			this.monthEnd = this.monthStart.add(Date.MONTH, 1);

			this.store.load({
				actionType: Zarafa.core.Actions['list'],
				params: {
					entryid : folder.get('entryid'),
					store_entryid : folder.get('store_entryid'),
					restriction : {
						startdate: startDate / 1000,
						duedate: dueDate / 1000
					}
				}
			});
		}
	},

	/**
	 * update function called when date has been changed (by clicking on date, through month picker, etc.)
	 * @param {Date} date The newly selected date
	 * @param {Boolean} forceRefresh
	 * @private
	 * @override
	 */
	update: function(date, forceRefresh)
	{
		Zarafa.calendar.ui.DatePicker.superclass.update.call(this, date, forceRefresh);
		if (!this.hidden && this.dateIsChanged(date)) {
			this.reloadStore(this.cells.first().dom.firstChild.dateValue, this.cells.last().dom.firstChild.dateValue);
		}
	},

	/**
	 * check if the passed date is in a different month or year than the current date
	 * @param {Date} date
	 * @return {Boolean}
	 * @private
	 */
	dateIsChanged: function(date)
	{
		var time = date.getTime();
		return (!this.monthStart || !this.monthEnd || time < this.monthStart.getTime() || this.monthEnd.getTime() <= time);
	},

	/**
	 * check whether setting for bolding days with appointments is set
	 * @return {Boolean}
	 * @private
	 */
	settingIsSet: function()
	{
		return container.getSettingsModel().get('zarafa/v1/contexts/calendar/datepicker_show_busy');
	},

	/**
	 * remove highlighting class from all cells
	 * @private
	 */
	clearCells: function()
	{
		this.cells.each(function(c){
			c.removeClass('x-date-busy');
		});
	},

	/**
	 * Function which is Sets a timer to update the highlighted date in the datepicker
	 * after the date has been changed to a new day during a session.
	 */
	setNextDayTimer: function ()
	{
		var diff = Date.diff(Date.MILLISECONDS, new Date().clearTime().add(Date.DAY, 1), new Date());
		Ext.defer(function () {
			if (this.activeDate.getTime() !== new Date().clearTime().getTime()) {
				this.activeDate = undefined;
				var model = this.navigationContext.model;
				var today = (new Date()).dateFormat(this.format);
				this.todayBtn.setTooltip(String.format(this.todayTip, today));
				model.setDate(new Date());
				model.load();
			}
			// Reset timer to referesh date picker
			this.setNextDayTimer();
		}, diff, this);
	}
});

Ext.reg('zarafa.datepicker', Zarafa.calendar.ui.DatePicker);