"""
 MoinMoin parser for calendars.
 Basically a bug fixed version of http://moinmoin.wikiwikiweb.de/MoinMoinCalendarExample
 Converted from a processor into a parser.
 Tested with MoinMoin 1.5.3

clach04 - 06-May-2006
"""

#
# clach04 06-May-2006
# shamelessly stolen parser example from 
# http://moinmoin.wikiwikiweb.de/UnifyParsersAndProcessors?highlight=%28Processors%29
# Added format_args to init as without, MoinMoin doesn't accept it

Dependencies = ["time"]

#####
##### from http://moinmoin.wikiwikiweb.de/MoinMoinCalendarExample
##### sys.stdout.write() calls replaced with request.write() calls
"""
 MoinMoin processor for calendars.
 This is currently version 1.0 (ntd 20030328)

 Work to do:
 v1.1 handle date ranges for events
 v2.0 full wiki processing in each cell of calendar
"""

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 toHTML(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 = """
<table width="100%%" border="1" cellspacing="0" cellpadding="2">
    <tr>
        <td bgcolor="%(captionBGColor)s" align="center" valign="middle">
            <font size="+2"><tt><b>%(month)s %(year)s</b></tt></font>
        </td>
    </tr>
</table>
        """


        dayCaptionTemplate = """
    <td align="right" valign="middle" bgcolor="%(captionBGColor)s" width="14%%"><tt><b>%(day)s</b></tt></td>
        """


        dayBodyTemplate = """
    <td valign="top" bgcolor="%(bodyBGColor)s" width="14%%"><p><tt>%(text)s</tt></p></td>
        """


        weekdayHeaderRowTemplate = """
        <td bgcolor="%(captionBGColor)s" align="center" valign="middle" width="14%%"><tt><b>%(weekday)s</b></tt></td>
        """


        weekdayHeaderRow = """
<table width="100%%" border="1" cellspacing="0" cellpadding="2">
    <tr>
        """

        for i in range(calendar.firstweekday( ), calendar.firstweekday( )+7):
            d = i%7
            weekdayHeaderRow += weekdayHeaderRowTemplate%{'weekday':EnglishDayText[d], 'captionBGColor':self.captionBGColor}
        weekdayHeaderRow += """
    </tr>
</table>
        """

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

        weeks = [ ]
        for week in calList:
            captions = "<tr>"
            bodies = "<tr>"
            for day in week:
                if day == 0:
                    caption = "&nbsp;"
                    body = "&nbsp;"
                    captionBGColor = self.bodyBGColor
                else:
                    captionBGColor = self.captionBGColor
                    caption = "%s"%day
                    if len(self.days[day]) ==0:
                        body = "&nbsp;"
                    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 += "</tr>"
            bodies += "</tr>"
            week = captions + bodies
            weeks.append(week)

        #-- Put it all together...
        html = captionTemplate%{'year': self.year, 'month': EnglishMonthText[self.month], 'captionBGColor':self.captionBGColor}
        html += weekdayHeaderRow
        html += '<table width="100%%" border="1" cellspacing="0" cellpadding="2">%s</table>'%''.join(weeks)

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

        return html


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

    lines=lines.split('\n') ## clach04 lines is a string not a list, etc. (using moin 1.5.3 src tarball as of 06-May-2006)
    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])
                        ## clach04, convert from Unicode to single byte,
                        ## (Python 2.3) apply() only accepts single byte strings as keys!
                        keyword = str(keyword ) 
                        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( )

    for item in cals:
        year, month, cal = item
        request.write("<p>")
        request.write(cal.toHTML( ))
        request.write("</p>")

"""
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.toHTML( )
"""



"""
parser code, template taken from
    http://moinmoin.wikiwikiweb.de/UnifyParsersAndProcessors?highlight=%28Processors%29
    
Added format_args to __init__. Without init(), MoinMoin doesn't accept it
and raises an exception.
"""
class Parser:
    """ a Calendar parser """

    def __init__(self, raw, request, format_args=None):
        # save call arguments for later use in format
        self.raw = raw
        self.request = request
        self.format_args = format_args

    def format(self, formatter):
        # this has the function of the old processor method
        # just use self.raw and self.request
        process(self.request, formatter, self.raw)



