#!/usr/bin/python
# -*- coding: UTF-8 -*-
# vim:ts=4:sw=4:ai:si:ci

# ogoObjects - Python module to "objectify" opengroupware XML-RPC calls
# Copyright 2006 Eliphas Levy Theodoro <lookup on euodeio.net>
# License: GPLv2

# Changelog
# 2006-02-17: v0.1
#   First version, release

# TODO:
#   Define optional team and participant filter for appointments
#   Objects for Jobs, Job, Contacts, Contact
#   I18N the module and remove static strings
#   Handle exceptions like connection errors

# BEGIN

import xmlrpclib, time, sys, locale
from mx import DateTime

# How to get right "Today" string?
today = DateTime.now()
todayStrs = {'en': 'Today', 'pt': 'Hoje' }

lang = locale.getdefaultlocale()[0]
if todayStrs.has_key(lang):
    todayStr = todayStrs[lang]
elif todayStrs.has_key(lang[:2]):
    todayStr = todayStrs[lang[:2]]
else:
    todayStr = todayStrs['en']

# Magic to get internationalized weekdays, 0 is monday
# Care to simplify it?
weekDays = [ i.strftime('%A').capitalize() for i in [DateTime.DateFrom('2001-01-%02d' % j) for j in range(1,8)] ]

def PrettyDate(dtime):
    if dtime.absdate == today.absdate:
        return dtime.strftime(todayStr + ', %H:%M')
    else:
        return dtime.strftime(weekDays[dtime.day_of_week]+', %d/%m %H:%M')

class Participant:
    def __str__(self):
        return self.name

    def __init__(self,partDict,connection):
        self.isPerson = False
        self.isTeam = False
        self.name = ''
        self.email = []
        self.isPerson = partDict.has_key('isPerson')
        self.isTeam = partDict.has_key('isTeam')
        if not self.isPerson and not self.isTeam:
            sys.stderr.write('DEBUGME: %s\n' % partDict)
            sys.exit(1)
        if self.isPerson:
            self.name = partDict['firstname'] + ' ' + partDict['name']
        elif self.isTeam:
            self.name = partDict['description']

        if self.isPerson:
            personDetail = connection.person.getByNumber(partDict['number'])
            if len(personDetail) > 0:
                if personDetail.has_key('extendedAttrs') \
                and personDetail['extendedAttrs'].has_key('email1'):
                    self.email.append(personDetail['extendedAttrs']['email1'])
        elif self.isTeam:
            teamDetail = connection.team.getMembersForTeam(partDict['number'])
            if len(teamDetail) > 0:
                for person in teamDetail:
                    personDetail = connection.person.getByNumber(person['number'])
                    if personDetail.has_key('extendedAttrs') \
                    and personDetail['extendedAttrs'].has_key('email1'):
                        self.email.append(personDetail['extendedAttrs']['email1'])
        self.name = self.name.encode('UTF-8')

class Appointment:
    def __cmp__(self,other):
        return cmp(self.start,other.start)

    def __str__(self):
        return '%s - %s\n%s' % (self.startPretty, self.endPretty, self.title)

    def __init__(self,appDict,connection):
        # When this appointment will happen.
        # -1: Before now, 0: Now, 1: Will happen today, 2: Will happen some other day
        toHappen = 1
        self.participants = []
        self.dic = appDict
        try:
            self.title =        appDict['title'].encode('UTF-8')
            self.start =        DateTime.mktime(time.strptime(appDict['startDate'].value, '%Y%m%dT%H:%M:%S'))
            self.end =          DateTime.mktime(time.strptime(appDict['endDate'].value, '%Y%m%dT%H:%M:%S'))
            self.startPretty =  PrettyDate(self.start)
            self.endPretty =    PrettyDate(self.end)

            if appDict.has_key('aptType'):
                self.type = appDict['aptType'].encode('UTF-8')
            else:
                self.type = ''

            if today > self.end: # already happened
                self.toHappen = -1
            elif today >= self.start and today <= self.end: # is happening
                self.toHappen = 0
            elif today.absdate == self.end.absdate: # will happen today
                self.toHappen = 1
            else: # will happen, but not today
                self.toHappen = 2

            for p in appDict['participants']:
                self.participants.append( Participant(p,connection) )

        except KeyError,e:
            sys.stderr.write('Erro: appDict %s\n' % e)
            sys.exit(1)

class Appointments:
    connection = None
    def connect(self,user,password,host='localhost',port=22000):
        url = 'http://%s:%s@%s:%d/RPC2' % (user,password,host,port)
        self.connection = xmlrpclib.Server( url )

    def fetch(self,start,end):
        fSpec = {}
        start = start + '.00:00'
        end   = end   + '.23:59'
        startDate = xmlrpclib.DateTime(time.strptime(start,'%Y-%m-%d.%H:%M'))
        endDate   = xmlrpclib.DateTime(time.strptime(end,'%Y-%m-%d.%H:%M'))
        fSpec['qualifier'] = {}
        fSpec['qualifier']['startDate'] = startDate
        fSpec['qualifier']['endDate'] = endDate
        fSpec['sortOrdering'] = ['startDate',]
        if type(self.connection) == type(None):
            raise Exception('NotConnected','XML-RPC connection not initialized, please connect first')
            return False
        appointments = self.connection.appointment.fetch(fSpec)
        apps = []
        for appointment in appointments:
            apps.append( Appointment(appointment,self.connection) )
        apps.sort()
        self.Appointments = apps
        return True

if __name__ == '__main__':
    if len(sys.argv) not in (1,3):
        sys.stderr.write("""Usage:\n%s startdate enddate\n\nEx: %s %s %s\n""" % \
            ( sys.argv[0], sys.argv[0], (today-1).date, today.date ))
        sys.exit(1)
    elif len(sys.argv) == 3:
        start = sys.argv[1]
        end = sys.argv[2]
    else:
        start = today.date
        end = start

    print "Username: ",
    user = sys.stdin.readline()[:-1]
    from getpass import getpass
    password = getpass("Password: ")

    appsObj = Appointments()
    appsObj.connect(user,password)
    appsObj.fetch(start,end)
    print "\nSchedule:\n"
    for appObj in appsObj.Appointments:
        happenOn = ''
        if appObj.toHappen == -1:
            happenOn = '(Happened)'
        elif appObj.toHappen == 0:
            happenOn = '(Now)'
        print '%s - %s: %s %s' % \
            ( appObj.startPretty, appObj.endPretty, appObj.title, happenOn )
        party = []
        for participant in appObj.participants:
            party.append(participant.name)
        party.sort()
        print '\t', '\n\t'.join(party)