<?php
	
	class EventCalendarWidget extends Widget
	{
		static $has_one = array(
			'Calendar' => 'Calendar'
		);
		
		public static $custom_jquery = false;
		public static $live = false;
		public static $async = false;
		public static $timeout = 0;
		
		public function Title()
		{
			return _t('EventCalendarWidget.TITLE', 'Calendar');
		}
		
		public function CMSTitle()
		{
			return _t('EventCalendarWidget.CMSTITLE', 'Calendar Widget');
		}
		
		public function Description()
		{
			return _t('EventCalendarWidget.DESCRIPTION', 'Show a calendar widget with links to events.');
		}
		
		public function getCMSFields()
		{
			$fields = new FieldSet();
			
			$calendars = DataObject::get('Calendar', null, '`Title` ASC');
			$fields->push(new DropdownField('CalendarID', _t('EventCalendarWidget.FIELD_CALENDAR', 'Parent calendar'), $calendars->map()));
			
			return $fields;
		}
		
		public function getController()
		{
			return "EventCalendarWidget_Controller/{$this->ID}";
		}
		
		public function getLive()
		{
			return Object::get_static($this->class, 'live');
		}
		
		public function getAsync()
		{
			return Object::get_static($this->class, 'async');
		}
		
		public function getTimeout()
		{
			return Object::get_static($this->class, 'timeout');
		}
		
		public function Content()
		{
			$custom_jquery = Object::get_static($this->class, 'custom_jquery');
			if(!$custom_jquery)
			{
				// require jQuery and jQuery UI
				Requirements::javascript('widget_EventCalendar/javascript/jquery-1.3.2.min.js');
				Requirements::javascript('widget_EventCalendar/javascript/jquery-ui-1.7.2.custom.min.js');
				Requirements::css('widget_EventCalendar/css/eventcalendarwidget/jquery-ui-1.7.2.custom.css');
				
				// include i18n file
				$calendar = $this->Calendar();
				if($calendar)
				{
					$calendarLanguage = strtolower(Object::get_static($calendar->class, 'language'));
					$languageFile = "ui.datepicker-{$calendarLanguage}.js";
					Requirements::javascript("widget_EventCalendar/javascript/ui/i18n/{$languageFile}");
				}
			}
			
			// include calendar script
			Requirements::javascript('widget_EventCalendar/javascript/EventCalendarWidget.js');
			
			// build the widget
			return parent::Content();
		}
	}
	
	class EventCalendarWidget_Controller extends Controller
	{
		static $url_handlers = array(
			'$ID/$Action/$StartDate/$EndDate' => 'handleAction'
		);
		
		private static function make_full_date(string &$dateText)
		{
			$dateRange = null;
			$dateParts = explode('-', $dateText);
			switch(count($dateParts))
			{
				case 3:
					$dateRange = 'day';
					break;
					
				case 2:
					$dateRange = 'month';
					$dateParts[] = '01';
					break;
					
				case 1:
					$dateRange = 'year';
					$dateParts[] = '01';
					$dateParts[] = '01';
					break;
				
				default:
					// invalid date
					return null;
			}
			
			$dateText = join('-', $dateParts);
			
			return $dateRange;
		}
		
		public function events(HTTPRequest $request)
		{
			// should not be called directly
			if(!Director::is_ajax())
				;//return new HTTPResponse(null, 403, 'Page can not be viewed');
			
			// get widget by ID (provided as first url param)
			$widget = DataObject::get_by_id('EventCalendarWidget', (int)$request->param('ID'));
			
			if(!$widget)
				return new HTTPResponse(null, 404, 'Could not find widget.');
			
			// get calendar belonging to widget
			$calendar = $widget->getComponent('Calendar');
			
			if(!$calendar)
				return new HTTPResponse(null, 404, 'Could not find calendar.');
			
			// get date configuration
			$startDate = $request->param('StartDate');
			$endDate = $request->param('EndDate');
			
			if(!$startDate)
			{
				$startDate = new sfDate(date('Y-m-d'));
				$endDate = new sfDate($startDate->addMonth(Calendar::$defaultFutureMonths)->date());
				$startDate->reset();
			}
			else
			{
				$dateRange = self::make_full_date($startDate);
				$startDate = new sfDate($startDate);
				
				if(!$endDate)
				{
					$endDate = new sfDate($startDate->date());
				}
				else
				{
					$dateRange = self::make_full_date($endDate);
					$endDate = new sfDate($endDate);
				}
				
				switch($dateRange)
				{
					case 'day':
						break;
					
					case 'month':
						$endDate->finalDayOfMonth();
						break;
						
					case 'year':
						$endDate->finalDayOfYear();
						break;
				}
			}
			
			// get events from calendar
			$events = $calendar->Events(null, $startDate, $endDate);
			
			// build event map
			$eventMap = array();
			foreach($events as $event)
			{
				// get start and end date for event
				$eventStartDate = new sfDate($event->StartDate);
				$eventEndDate = ($event->EndDate) ? new sfDate($event->EndDate) : new sfDate($event->StartDate);
				
				// truncate event at end of selected time
				if($eventEndDate > $endDate)
					$eventEndDate = new sfDate($endDate->date());
				
				// add all dates of event to map
				for($eventStartDate; $eventStartDate <= $eventEndDate; $eventStartDate->addDay(1))
				{
					// get date in normal formatting
					$dateText = $eventStartDate->format('Y-m-d');
					
					// create an array for this date's events if necessary
					if(!isset($eventMap[$dateText]))
						$eventMap[$dateText] = array();
					
					// add the event to this date's events
					$eventMap[$dateText][] = $event->EventTitle();
				}
			}
			
			// create JSON list of events
			$json = Convert::array2json($eventMap);
			
			// create a JSON response
			$jsonResponse = new HTTPResponse($json);
			$jsonResponse->addHeader('Content-Type', 'text/javascript');
			$jsonResponse->addHeader('Content-Length', strlen($json));
			
			return $jsonResponse;
		}
	}
?>