#!/usr/bin/env python
#
# Copyright 2010 Eric Entzel <eric@ubermac.net>
#

from ecal_wsgi import EcalWSGIApplication
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp.mail_handlers import InboundMailHandler
from gdata.service import RequestError
import logging
import urllib
from datetime import datetime
from ecal_users import EmailUser
import google_api
import outgoing_mail
import re


class FeedbackHandler(object):
    """Abstract class to send email feedback to the user that their
    event creation succeeded/failed.

    Swallows all exceptions so that the HTTP request that GAE sends us
    for incoming mail doesn't throw a 500 error -- if it did, GAE
    would keep retrying and creating duplicate events.

    Subclasses must implement a values() method and a template_name
    attribute.  Subclasses can optionally implement a warning
    attribute, which will be logged.
    """
    def send(self):
        if hasattr(self, 'warning'):
            logging.warn(self.warning)        
        try:
            outgoing_mail.send(self.message.sender, self.template_name,
                               self.values())
        except:
            logging.warn("unable to send email to %s using template %s" %
                         (self.message.sender, self.template_name))


class NoSuchAddressHandler(FeedbackHandler):
    template_name = 'no_such_address'
    def __init__(self, message, adr):
        self.message = message
        self.adr = adr
        self.warning = "Couldn't create event for user with address " + self.adr
        
    def values(self):
        return { 'address': self.adr,
                 'subject': self.message.subject }


class SuccessHandler(FeedbackHandler):
    template_name = 'event_created'
    def __init__(self, message, event):
        self.message = message
        self.event = event

    def values(self):
        start_time = self.event.FindExtensions(tag='when')[0].attributes['startTime']
        return { 'link': self.event.GetHtmlLink().href,
                 'when': CreateEventHandler._format_date(start_time),
                 'title': self.event.title.text }

        
class CreateEventHandler(InboundMailHandler):
    # self.request.path will contain something like:
    # /_ah/mail/89c33b71-b5a3-4e0a-bbb3-8283d337cbca%40myeventbot.appspotmail.com
    def _get_email_address(self):
        decoded_path = urllib.unquote(self.request.path)
        return decoded_path.replace('/_ah/mail/', '')

    def _get_user(self):
        local_part = self._get_email_address().split('@')[0]
        query = EmailUser.gql("WHERE email_address = :email", email=local_part)
        try:
            current_user = query.fetch(1)[0]
            return current_user
        except IndexError:
            return None

    @staticmethod
    def _format_date(str):
        """Format a date from GCal into a user-friendly string.

        >>> CreateEventHandler._format_date("2011-02-11T15:00:00.000-07:00")
        'Fri Feb 11 03:00 PM'
        >>> CreateEventHandler._format_date("2011-06-11T15:20:12.000-06:00")
        'Sat Jun 11 03:20 PM'
        """
        # TODO: Remove leading zero from hour
        str = re.sub(r".000-.*$", "", str)
        try:
            date = datetime.strptime(str, "%Y-%m-%dT%H:%M:%S")
            return date.strftime("%a %b %e %I:%M %p")
        except ValueError:
            date = datetime.strptime(str, "%Y-%m-%d")            
            return date.strftime("%a %b %e")

    def receive(self, message):
        current_user = self._get_user()
        if current_user == None:
            NoSuchAddressHandler(message, self._get_email_address()).send()
            return
        token = current_user.auth_token
        try:
            event = google_api.quickadd_event_using_token(message.subject, token)
        except RequestError, err:
            if err.status == 401:
                logging.info("it looks like you've revoked your token")
            else:
                logging.info("couldn't create event")
            return
        current_user.last_action = datetime.now()
        current_user.put()
        SuccessHandler(message, event).send()


def main():
    application = EcalWSGIApplication([CreateEventHandler.mapping()])
    run_wsgi_app(application)

if __name__ == "__main__":
  main()

@@ -3890,14 +3890,25 @@
 err.
+args%5B0%5D%5B'
 status
+'%5D
  == 

Check RequestError status correctly.