#! /usr/bin/env python
########################################################################
# COPYRIGHT_BEGIN
#
#           mical
#           Minimal iCalendar utilities
#
# Copyright (C) 2007, David Arnold
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2, as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# COPYRIGHT_END
########################################################################
# $ZeroXOne: mical/micreply,v 1.8 2007/06/06 00:48:10 d Exp $
########################################################################

# RFC-2446
# Section 3.2.3 deals with REPLY

import datetime, smtplib, sys, os, vobject
from   email.MIMEText import MIMEText
from   email.MIMEMultipart import MIMEMultipart
from   optparse import OptionParser
from   mical import VERSION

PROGRAM = os.path.basename(sys.argv[0])

########################################################################

def usage(msg=None):
    if msg:
        print msg
    print "Usage: %s [-i index] action" % PROGRAM
    return


def prefixes(s):
    """Return list of possible prefixes for the supplied string."""

    l = []
    for i in range(len(s)+1):
        l.append(s[:i])
    return l


def reply(request, answer):

    # Get my email address
    try:
        f = open("%s/.mical/me" % os.environ["HOME"])
        me = f.read().strip()
        f.close()
    except IOError:
        usage("mical not initialized.  Please run micsetup")
        sys.exit(1)

    # Get required event properties
    organizer = request.vevent.organizer.value.split(":")[1]
    uid = request.vevent.uid.value
    sequence = request.vevent.sequence.value
    summary = request.vevent.summary.value
    start = request.vevent.dtstart.value

    if hasattr(request.vevent, "dtend"):
        end = request.vevent.dtend.value
    elif hasattr(request.vevent, "duration"):
        duration = request.vevent.duration.value
        end = start + duration

    if hasattr(request.vevent, "location"):
        location = request.vevent.location.value
    else:
        location = "Unspecified"

    # Create reply iCalendar object
    reply = vobject.iCalendar()
    reply.add('method')
    reply.method.value = "REPLY"
    
    reply.add('vevent')
    reply.vevent.add('attendee')
    reply.vevent.attendee.value = "MAILTO:" + me
    reply.vevent.attendee.params["PARTSTAT"] = [answer.upper()]
    reply.vevent.add('organizer')
    reply.vevent.organizer.value = "MAILTO:" + organizer
    reply.vevent.add('uid')
    reply.vevent.uid.value = uid
    reply.vevent.add('sequence')
    reply.vevent.sequence.value = sequence
    reply.vevent.add('dtstamp')
    reply.vevent.dtstamp.value = datetime.datetime.now()

    # Ensure Outlook prints the reply nicely
    reply.vevent.add('location')
    reply.vevent.location.value = location
    reply.vevent.add('dtstart')
    reply.vevent.dtstart.value = start
    if hasattr(request.vevent, "dtend"):
        reply.vevent.add('dtend')
        reply.vevent.dtend.value = end
    elif hasattr(request.vevent, "duration"):
        reply.vevent.add('duration')
        reply.vevent.duration.value = duration
    
    # Create reply email text
    #text = "I have %s your invitation to '%s'\r\n" % (answer.lower(), summary)
    
    # Create reply email
    message = MIMEText(reply.serialize(), "calendar; method=REPLY")

    message['Subject'] = summary
    message['From'] = me
    message['Cc'] = me
    message['To'] = organizer
    message['X-Mailer'] = PROGRAM + " v" + VERSION

    # Send email
    mailer = smtplib.SMTP()
    mailer.connect()
    mailer.sendmail(me, [organizer], message.as_string())
    mailer.close()

    # Print action
    print answer.capitalize() + ": " + summary
    return


def main():

    # Parse arguments
    parser = OptionParser(description="Send an email reply to a specified "
                          "iCalendar meeting invitation, accepting or "
                          "declining as specified.  Without a saved initation "
                          "index number, read the invitation text from the "
                          "standard input device.",
                          usage="%prog [-i index] accepted|declined",
                          version=PROGRAM + "-" + VERSION)
    parser.add_option("-i", "--index", dest="index", help="Index of saved event", metavar="NUM")
    (options, args) = parser.parse_args()
    
    if len(args) != 1:
        usage("Illegal options")
        sys.exit(1)

    event_id = options.index
    action = args[0]

    if event_id:
        # Find event matching supplied identifier
        try:
            events = os.listdir("%s/.mical" % os.environ["HOME"])
        except OSError:
            usage("No saved events found")
            sys.exit(1)

        if event_id not in events:
            usage("No such event: %s" % event_id)
            sys.exit(1)

        # Open event file
        f = open("%s/.mical/%s" % (os.environ["HOME"], event_id))
    else:
        f = sys.stdin

    # Read event data
    request = vobject.readOne(f)
    f.close()
    
    # Perform requested action
    if action.lower() in prefixes("accepted"):
        reply(request, "accepted")
    elif action.lower() in prefixes("declined"):
        reply(request, "declined")
    else:
        usage("Unrecognised action: %s" % action)
        sys.exit(1)


if __name__ == "__main__":
    main()


########################################################################
