﻿/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * File:		SMCalendar.js
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 * Purpose:	javascript calendar control wrapper
 *			
 * Copyright:	Synaptic Mash 2008 All Rights Reserved
 *
 * Developer contact:	Jason Hillier <jason.hillier@synapticmash.com>
 * 
 * Notes:
 * ------
 *	This is a complete wrapper -- no modifications have been made to fullcalendar -- well except the agenda view stuff
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 

var SMCalendar = Class.create({
	Name: null,
	_Options: null,
	_newEventIndex: 0,
	_Tooltip: null,
	_workingEvent: null, //hack for accessing event data that is currently being shown in tooltip
	
	initialize: function(id, options)
	{
		this._Tooltip = $(id).SMTooltip;
		this._Tooltip.deactivate();
		
		this.Name = id;
		this._Options = options;
		
		SMLayoutManager.RegisterControl(this);
	},
	
	//super awesome hack: this gets called from the StartTime and EndTime datepicker controls that were rendered in the tooltip.
	IChangeDate: function(fromId, value)
	{
		var controlId = SMLayoutManager.GetDebugID(fromId);
		
		SMLayoutManager.Log.Debug(value);
		
		if (controlId.indexOf("EndTime") > 0)
		{
			if (this._workingEvent.start < value)
				this._workingEvent.end = value;
		}
		else if (controlId.indexOf("StartTime") > 0)
		{
			if (this._workingEvent.end > value)
				this._workingEvent.start = value;
		}
		
		this.OnEventChange(this._workingEvent);
		
		this.getCalendar().fullCalendar('rerenderEvents');
	},
	
	ChangeEventCSS: function(css)
	{
		this._workingEvent.CustomCSS = css;
		
		this.getCalendar().fullCalendar('rerenderEvents');
	},
	
	getCalendar: function()
	{
		return $j('#' + this.Name + "_Calendar");
	},
	
	dayClick: function( date, allDay, jsEvent, view)
	{
		if (!this._Options.EnableAdd)
			return;
		
		var endDate = new Date(date.getTime() + (60 * 60 * 1000)); //add 60 minutes
		this.AddEvent({EventID: 'new_' + this._newEventIndex, Title: 'New Event', allDay: false, StartDate: date, EndDate: endDate});
		
		this._newEventIndex++;
	},
	
	eventClick: function( calEvent, jsEvent, view )
	{
		this._Tooltip.options.hideEffect = null;
		this._Tooltip.hide();
		
		this._workingEvent = calEvent;
		
		var txEvent = _SMCalendar.ExportEventData(calEvent);
		
		var eventDIV = $(jsEvent.target).up(".fc-event");
		
		if (!this._Options.EnableTooltip)
			return;
		
		//debugger;
		if (calEvent.Link != null)
		{
			window.location = calEvent.Link;
		}
		else if (calEvent.LightwindowData != null)
		{
			//show lightwindow instead of tooltip
			SMLightWindow.ShowURL(calEvent.LightwindowData.TargetURL, calEvent.LightwindowData.EncodedParameters);
		}
		else
		{
			//else use tooltip
			this._Tooltip.element = eventDIV;
			this._Tooltip.target = eventDIV;
			this._Tooltip.options.ajax.context = Object.toJSON(txEvent);
			this._Tooltip.activate();
			this._Tooltip.forceShow();
		}
	},
	
	hideTooltip: function()
	{
		this._Tooltip.hide();
		this._Tooltip.deactivate();
		
		this._workingEvent = null;
	},
	
	setTitle: function(eventID, newTitle)
	{
		var event = this.getCalendar().fullCalendar('clientEvents', eventID)[0];
		
		event.title = newTitle;
		
		this.OnEventChange(event);
	},
	
	DeleteEventById: function(eventID)
	{
		var event = this.getCalendar().fullCalendar('clientEvents', eventID)[0];
		
		this.DeleteEvent(event);
	},
	
	DeleteEvent: function(event)
	{
		this.getCalendar().fullCalendar( 'removeEvents', event._id );
		
		var txEvent = _SMCalendar.ExportEventData(event);
		SMLayoutManager.FireAjaxEventType(this.Name, 'SMCalendar', 'OnDeleteEvent', { CalendarEvent: txEvent });
	},
	
	AddEvent: function(calendarEvent)
	{
		//transponse to event
		var event = {_id: calendarEvent.EventID, title: calendarEvent.Title, allDay: calendarEvent.allDay, start: calendarEvent.StartDate, end: calendarEvent.EndDate };
		
		this.getCalendar().fullCalendar('addEventSource', [ event ]);
		
		//this.getCalendar().fullCalendar({events: [ event ]});
		
		this.getCalendar().fullCalendar('rerenderEvents');
		
		this.OnEventAdd(event);
	},
	
	eventRender: function(event, element)
	{
		if (this._Options.EnableItemDelete)
		{
			var eTime = element.find('.fc-event-time')[0];
			eTime.innerHTML = "<div class=\"delete\" style=\"display:inline;\" onclick=\"SMLayoutManager.GetControl('" + this.Name +"').deleteClick('" + event._id + "');\">x</div>&nbsp;&nbsp;&nbsp;" + eTime.innerHTML;
		}
		
		if (event.CustomCSS != null && event.CustomCSS != '')
		{
			//debugger;
			element.addClass(event.CustomCSS);
		}
		
		/*
		if (event.titleHTML != null && event.titleHTML != '')
		{
			var eTitle = element.find('.fc-event-title')[0];
			eTitle.innerHTML = event.titleHTML;
		}
		*/
		
		//var eTitle = element.find('.fc-event-title')[0];
		//$j(eTitle).bind('click', { calendarEvent: event }, this.editTitleClick);
		
	},
	
	eventDrop: function(event,dayDelta,minuteDelta,allDay,revertFunc)
	{
		this.OnEventChange(event);
	},
	
	eventResize: function( event, dayDelta, minuteDelta, revertFunc, jsEvent, ui, view )
	{
		this.OnEventChange(event);
	},
	
	deleteClick: function(eventID)
	{
		var event = this.getCalendar().fullCalendar('clientEvents', eventID)[0];
		
		if (confirm("Are you sure you want to delete event '" + event.title + "'?"))
		{
			this.DeleteEvent(event);
		}
	},
	
	editTitleClick: function(e)
	{
		var event = e.data.calendarEvent;
		
		//alert("edit " + event._id);
	},
	
	OnEventAdd: function(event)
	{
		var txEvent = _SMCalendar.ExportEventData(event);
		
		//SMLayoutManager.Log.Debug("a:", event);
		
		SMLayoutManager.FireAjaxEventType(this.Name, 'SMCalendar', 'OnEventAdd', { CalendarEvent: txEvent }, { onSuccessEventResponse: this.OnEventChange_Completed.bindAsEventListener(this, event) });
	},
	
	OnEventChange: function(event)
	{
		var txEvent = _SMCalendar.ExportEventData(event);
		
		//SMLayoutManager.Log.Debug("a:", event);
		
		SMLayoutManager.FireAjaxEventType(this.Name, 'SMCalendar', 'OnEventChange', { CalendarEvent: txEvent }, { onSuccessEventResponse: this.OnEventChange_Completed.bindAsEventListener(this, event) });
	},
	
	OnEventChange_Completed: function(newEventData, event)
	{
		var old_id = event._id;
		
		var calendarEvent = _SMCalendar.ImportEventData(newEventData.CalendarEvent);
		event._id = calendarEvent._id;
		event.title = calendarEvent.title;		
		event.LightwindowData = calendarEvent.LightwindowData;
		
		this.getCalendar().fullCalendar('updateEvent', event);
		
		SMLayoutManager.Log.Trace("Updated event '" + old_id + "' to ", calendarEvent);
	},
	
	OnFetchEvents: function(start, end, callback)
	{
		SMLayoutManager.FireAjaxEventType(this.Name, 'SMCalendar', 'OnFetchEvents', { FetchRange: { StartTime: start, EndTime: end } }, { onSuccessEventResponse: this.OnFetchEvents_Complete.bindAsEventListener(this, callback) });
	},
	
	OnFetchEvents_Complete: function(response, callback)
	{
		SMLayoutManager.Log.Debug("fetch ", response, callback);
		
		for(var i=0; i<response.CalendarEvents.length; i++)
		{
			SMLayoutManager.Log.Debug(response.CalendarEvents[i]);
			response.CalendarEvents[i] = _SMCalendar.ImportEventData(response.CalendarEvents[i]);
		}
		
		callback(response.CalendarEvents);
	}
});

var _SMCalendar={
	ImportEventList: function(eventList)
	{
		newEventList = new Array();
		
		for(var i=0; i<eventList.length; i++)
		{
			newEventList.push(_SMCalendar.ImportEventData(eventList[i]));
		}
		
		return newEventList;
	},
	
	ImportEventData: function(event)
	{
		var eventCopy = {
			_id: event.EventID,
			title: event.Title,
			agendaTitleExt: event.AgendaTitleExt,
			Link: event.Link,
			LightwindowData: event.LightwindowData,
			allDay: event.allDay,
			start: MicrosoftJSONSerializationFix(event.StartDate),
			end: MicrosoftJSONSerializationFix(event.EndDate),
			CustomCSS: event.CustomCSS};
		
		return eventCopy;
	},
	
	ExportEventData: function(event)
	{
		var eventCopy = {
			EventID: event._id,
			Title: event.title,
			AgendaTitleExt: event.agendaTitleExt,
			allDay: event.allDay,
			StartDate: event.start,
			EndDate: event.end };
		
		return eventCopy;
	}
}

