"""
 MoinMoin processor for calendars.
 This is currently version 1.5 (nm 20040707)

 $Id: Calendar.py,v 1.4 2004/07/07 14:12:10 nigel Exp $

 This calendar module has been seriously refactored so that it outputs
 wiki text format which is pushed through the formatter.
 This means wiki markup and links within the cells work - however you are
 restricted to keeping the per-date cell stuff to a single line, and its
 going to be pretty easy to come up with combinations of markup in the
 cells which conflict with the markup I am adding and break things.

 This is very much a trial of the idea - comments welcome...

 History:
   20030328 ntd (1.0) - Original version
   20040702 cpj       - Modified output code to avoid stdout
   20040707 nm  (1.5) - Rewrote to output wikitext rather than HTML
                        and pass that text to the formatter.

 Work to do:
   Handle date ranges for events
   Hook to stylesheets?
   Can I make the title show up bigger?
   
 Input Example

   {{{
   #!Calendar (-)
   OPTION:bodyBGColor=#DDDDDD
   OPTION:captionBGColor=#CCCCFF
   OPTION:firstWeekDay=6
   20030328: Calendar 1.0 released
   20030301: First of the month
   20030331: End of the month
   20030331: Last day...
   20030401: First day of next month
   20030430: Link to FrontPage
   }}}

"""

from MoinMoin.parser import wiki
import string, sys
import calendar

class EventCalendar:
	def __init__(self, year, month, **kwargs):
		self.year = year
		self.month = month
		self.days = { }
		self.captionBGColor = "#D0D0D0"
		self.bodyBGColor = "#FFFFFF"
		self.firstWeekDay = calendar.SUNDAY


		#-- Process keyword arguments.
		if kwargs.has_key("captionBGColor"):
			self.captionBGColor = kwargs['captionBGColor']
		if kwargs.has_key("bodyBGColor"):
			self.bodyBGColor = kwargs['bodyBGColor']
		if kwargs.has_key("firstWeekDay"):
			self.firstWeekDay = int(kwargs['firstWeekDay'])


		lastDay = calendar.monthrange(year, month)[1]
		for i in xrange(1,lastDay+1):
			self.days[i] = [ ]

	def addEvent(self,day,event):
		self.days[day].append(event)

	def toWIKI(self):
		EnglishMonthText = {
			1: 'January',
			2: 'February',
			3: 'March',
			4: 'April',
			5: 'May',
			6: 'June',
			7: 'July',
			8: 'August',
			9: 'September',
			10: 'October',
			11: 'November',
			12: 'December'
		}

		EnglishDayText = {
			0: 'Monday',
			1: 'Tuesday',
			2: 'Wednesday',
			3: 'Thursday',
			4: 'Friday',
			5: 'Saturday',
			6: 'Sunday'
		}

		#-- Get the first weekday defined in the calendar module and save it temporarily
		fwd = calendar.firstweekday( )

		#-- Set the first weekday
		calendar.setfirstweekday(self.firstWeekDay)


		captionTemplate = """||<tablewidth="100%%" rowbgcolor="%(captionBGColor)s" :-7>'''%(month)s %(year)s'''||"""

		dayCaptionTemplate = """||<%(captionBGColor)s 14%%)> '''`%(day)s`'''"""

		dayBodyTemplate = """||<%(bodyBGColor)s 14%%> %(text)s"""

		weekdayHeaderRowTemplate = """||<%(captionBGColor)s )14%%> '''`%(weekday)s`'''"""

		# Build a weekday header row - could be reused if there is more than one calendar
		weekdayHeaderRow = ""
		for i in range(calendar.firstweekday( ), calendar.firstweekday( )+7):
			d = i%7
			weekdayHeaderRow += weekdayHeaderRowTemplate%{'weekday':EnglishDayText[d], 'captionBGColor':self.captionBGColor}
		weekdayHeaderRow += '||'

		calList = calendar.monthcalendar(self.year, self.month)
		weekRows = len(calList)

		outrows = [ ]
		outrows.append(captionTemplate%{'year': self.year,
						'month': EnglishMonthText[self.month],
						'captionBGColor':self.captionBGColor})
		outrows.append(weekdayHeaderRow)
		for week in calList:
			captions = ""
			bodies = ""
			for day in week:
				if day == 0:
					caption = " "
					body = " [[BR]] "
					captionBGColor = self.bodyBGColor
				else:
					captionBGColor = self.captionBGColor
					caption = "%s" % day
					if len(self.days[day]) ==0:
						body = " [[BR]] "
					else:
						body = ""
						for event in self.days[day]:
							body += "%s[[BR]]" % event
				captions += dayCaptionTemplate % {'day':caption,
								  'captionBGColor':captionBGColor}
				bodies += dayBodyTemplate % {'text':body,
							     'bodyBGColor':self.bodyBGColor}
			captions += "||"
			bodies += "||"
			outrows.append(captions)
			outrows.append(bodies)

		# add some forced space
		outrows.append("[[BR]]")

		#-- Restore the first week day that was previously defined in the calendar module.
		calendar.setfirstweekday(fwd)

		return str.join("\n", outrows)


def process(request, formatter, lines):
	events = { }
	kwargs = { }

	for line in lines:
		text = string.strip(line)

		if len(text) > 0:
			i = string.find(text,":")
			if i >= 0:
				if text[:i] == 'OPTION':
					option = text[i+1:]
					j = string.find(option,"=")
					if j > 0:
						keyword = string.strip(option[:j])
						value = string.strip(option[j+1:])
						kwargs[keyword] = value
				else:
					eventDate = text[:i]
					eventText = text[i+1:]

					eventYear = int(eventDate[:4])
					eventMonth = int(eventDate[4:6])
					eventDay = int(eventDate[6:8])

					if not events.has_key(eventYear):
						events[eventYear] = { }
					if not events[eventYear].has_key(eventMonth):
						events[eventYear][eventMonth] = { }
					if not events[eventYear][eventMonth].has_key(eventDay):
						events[eventYear][eventMonth][eventDay] = [ ]
						
					events[eventYear][eventMonth][eventDay].append(eventText)

	cals = []
	for year in events.keys( ):
		for month in events[year].keys( ):
			cal = apply(EventCalendar, (year, month), kwargs)
			for day in events[year][month].keys( ):
				for event in events[year][month][day]:
					cal.addEvent(day,event)
			cals.append((year,month,cal))
	cals.sort( )
	output = []
	for item in cals:
		year, month, cal = item
		output.append("")
		output.append(cal.toWIKI( ))
		output.append("")
		output.append("")
	wikiizer = wiki.Parser("\n".join(output), request)
	wikiizer.format(formatter)

"""
march = EventCalendar(2003,3)
march.addEvent(14, "St. Patrick's Day")
march.addEvent(20, "First Day of Spring")
march.addEvent(20, "Joe's Birthday")
print march.toWIKI( )
"""
