"""
Gets pending events from the system in iCalendar (RFC 2445) format.
"""
# Copyright © 2004-2008 Saugus.net, Inc.
# All Rights Reserved.

# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.


RESPONSE.setHeader('Content-Type','text/calendar')

from DateTime import DateTime
zcat=context.portal_catalog
cal=context.portal_calendar
# lines shouldn't be longer than 75 bytes according to the spec.
# The default value here gives us some slack.
lineLen=60

# Weirdly the spec insists on that least efficient of line endings: the
# CRLF rather than either the CR or LF by itself.  This section just
# handles the (mostly constant) header.

iCalendar='BEGIN:VCALENDAR\r\nCALSCALE:GREGORIAN\r\n'
iCalendar='%sX-WR-TIMEZONE;VALUE=TEXT:%s\r\n'%(iCalendar,DateTime().timezone())
iCalendar='%sX-WR-CALDESC;VALUE=TEXT:Zope CMF Calendar%s\r\n'%(iCalendar)
iCalendar='%sPRODID:-//Zope CMF//iCalendar 1.0a//%s\r\n'%(iCalendar,context.Language() or 'EN')
iCalendar='%sX-WR-CALNAME;VALUE=TEXT:%s Calendar\r\n'%(iCalendar,context.getPublisher())
iCalendar='%s%s\r\n'%(iCalendar,'VERSION:2.0')

# This section handles the individual events in the calendar, converting
# them to iCalendar VEVENTS.

for objCat in zcat(portal_type=cal.getCalendarTypes(),
                   review_state='published',
                   start=DateTime().earliestTime(),
                   start_usage='range:min',
                   sort_on='start',
                   sort_order='reverse'):
  obj=objCat.getObject()
  iCalendar='%sBEGIN:VEVENT\r\n'%(iCalendar)

  # All iCalendar dates are unfortunately a bastardization of HTML4 style dates
  
  creationDate=DateTime(obj.CreationDate()).HTML4().replace('-','').replace(':','')
  startTime=DateTime.HTML4(obj.start()).replace('-','').replace(':','')
  endTime=DateTime.HTML4(obj.end()).replace('-','').replace(':','')
  iCalendar='%sDTSTAMP:%s\r\n'%(iCalendar,creationDate)
  iCalendar='%sUID:%s\r\n'%(iCalendar,obj.event_email or obj.id)

  # We're living a little dangerously by not checking the length of the title
  # and hoping it (plus the string "SUMMARY:") will be under the 75 bytes.
  # We're also relying on it not containing HTML.
  
  title=context.html2txt(obj.title.strip()).replace(',','\,').replace(';','\;') or 'None Provided'
  iCalendar='%sSUMMARY:%s\r\n'%(iCalendar,title)

  # This section "folds" the potentially long description via the spec
  
  description=''
  workStr=context.html2txt(obj.description.strip()).replace('\r',' ').replace('\n',' ').replace(',','\,').replace(';','\;')
  numLinesToBeProcessed=len(workStr)/lineLen
  startingChar=0
  while numLinesToBeProcessed>=1:
    description='%s%s\r\n '%(description,workStr[startingChar:startingChar+lineLen])
    startingChar+=lineLen
    numLinesToBeProcessed-=1
  description='%s%s'%(description,workStr[startingChar:])

  # The DESCRIPTION, ORGANIZER, CONTACT, and LOCATION are all optional but
  # are filled in here if provided.
  
  if description:
    iCalendar='%sDESCRIPTION:%s\r\n'%(iCalendar,description)
  if obj.event_email:
    iCalendar='%sORGANIZER:MAILTO:%s\r\n'%(iCalendar,obj.event_email)
  if obj.event_phone:
    iCalendar='%sCONTACT:%s\r\n'%(iCalendar,obj.event_phone)
  if obj.location:
    iCalendar='%sLOCATION:%s\r\n'%(iCalendar,context.html2txt(obj.location.strip()))

  iCalendar='%sDTSTART:%s\r\n'%(iCalendar,startTime)
  iCalendar='%sDTEND:%s\r\n'%(iCalendar,endTime)
  iCalendar='%sTZNAME:%s\r\n'%(iCalendar,DateTime().strftime('%Z'))
  iCalendar='%sEND:VEVENT\r\n'%(iCalendar)

# This section handles the constant footer.

iCalendar='%sEND:VCALENDAR\r\n'%(iCalendar)

return iCalendar

