import dbus
import dbus.glib
import logging
import string
import vobject
from datetime import datetime
from dateutil.tz import tzutc, tzlocal

log = logging.getLogger("modules.Hamster")

import conduit
import conduit.TypeConverter as TypeConverter
import conduit.dataproviders.DataProvider as DataProvider
import conduit.dataproviders.AutoSync as AutoSync
import conduit.Exceptions as Exceptions
import conduit.datatypes.Event as Event
import conduit.utils as Utils

from gettext import gettext as _

MODULES = {
	"HamsterCalendarTwoWay" :        { "type": "dataprovider"    },
}

class HamsterCalendarTwoWay(DataProvider.TwoWay, AutoSync.AutoSync):
    """
    LUID is the tomboy uid string
    """
    _name_ = _("Hamster")
    _description_ = _("Synchronize your Hamster activities")
    _category_ = conduit.dataproviders.CATEGORY_OFFICE
    #_module_type_ = "twoway"
    _module_type_ = "source"
    _in_type_ = "event"
    _out_type_ = "event"
    _icon_ = "gworldclock"
    _configurable_ = False
    
    HAMSTER_DBUS_PATH = "/org/gnome/Hamster"
    HAMSTER_DBUS_IFACE = "org.gnome.Hamster"
    #HAMSTER_MIN_VERSION = (0, 5, 10)
    #HAMSTER_COMPLETE_XML_VERSION = (0 ,9 ,0)
    
    def __init__(self, *args):
        DataProvider.TwoWay.__init__(self)
        AutoSync.AutoSync.__init__(self)
        self.events = {}
        self.remoteHamster = None
        #self.supportsCompleteXML = False

        self._connect_to_hamster()

    def _connect_to_hamster(self):
        if self.remoteHamster != None:
            return True

        bus = dbus.SessionBus()
        if Utils.dbus_service_available(HamsterCalendarTwoWay.HAMSTER_DBUS_IFACE, bus):
            obj = bus.get_object(HamsterCalendarTwoWay.HAMSTER_DBUS_IFACE, HamsterCalendarTwoWay.HAMSTER_DBUS_PATH)
            app = dbus.Interface(obj, "org.gnome.Hamster")
            #version = tuple(int(item) for item in str(app.Version()).split('.'))
            self.remoteHamster = app
#            self.remoteHamster.connect_to_signal("EventAdded", lambda uid: self.handle_added(str(uid)))
#            self.remoteHamster.connect_to_signal("EventSaved", lambda uid: self.handle_modified(str(uid)))
#            self.remoteHamster.connect_to_signal("EventDeleted", lambda uid, x: self.handle_deleted(str(uid)))
            log.info("Using Hamster!")
            return True
        return False

#    def _update_event(self, uid, event):
#        log.debug("Updating event uid: %s" % uid)
#        if note.get_xml() != None:
#            ok = self.remoteTomboy.SetNoteCompleteXml(
#                                    uid,
#                                    note.get_xml()
#                                    )
#        else:
#            ok = self.remoteTomboy.SetNoteContents(
#                                    uid,
#                                    note.get_contents()
#                                    )
#
#        if not ok:
#            raise Exceptions.SyncronizeError("Error setting Tomboy note content (uri: %s)" % uid)

    def _get_event_mtime(self, uid):
        log.debug("getting mtime for %s" % uid)
        f = self.events[uid]
        log.debug(f)
        log.debug(f['end_time'])
        ts = Utils.datetime_from_timestamp(int(f['end_time'])).replace(tzinfo=tzlocal()).astimezone(tzutc()).replace(tzinfo=None)
        return ts

    def _get_event(self, uid):
        #Get the whole xml and strip out the tags
        log.debug("Getting event: %s" % uid)

        xml = None
#        if self.supportsCompleteXML:
#            xml = str(self.remoteTomboy.GetNoteCompleteXml(uid))

        f = self.remoteHamster.GetFactById(dbus.UInt32(uid))

        iCalEvent = vobject.iCalendar().add('vevent')
        iCalEvent.add('uid').value = str(uid)
        iCalEvent.add('summary').value = f['category'] + ': ' + f['name']
        iCalEvent.add('description').value = f['description']
        iCalEvent.add('dtstart').value = Utils.datetime_from_timestamp(int(f['start_time'])).replace(tzinfo=tzlocal()).astimezone(tzutc()).replace(tzinfo=None)
        iCalEvent.add('dtend').value = Utils.datetime_from_timestamp(int(f['end_time'])).replace(tzinfo=tzlocal()).astimezone(tzutc()).replace(tzinfo=None)

        iCalEvent.add('last-modified').value = Utils.datetime_from_timestamp(int(f['end_time'])).replace(tzinfo=tzlocal()).astimezone(tzutc()).replace(tzinfo=None)
        retstr = iCalEvent.serialize()
        log.debug(retstr)
        return retstr

#    def _create_event(self, event):
#        uid = str(self.remoteHamster.CreateNamedEvent(note.get_title()))
#        self._update_note(uid, note)
#        return uid

    def initialize(self):
        """
        Loads the hamster source if the user has used hamster before
        """
        return True

    def refresh(self):
        DataProvider.TwoWay.refresh(self)
        self.events = {}
        if self._connect_to_hamster():
            #self.notes = [str(i) for i in self.remoteHamster.GetFacts(1,99999999)]
            for f in self.remoteHamster.GetFacts(dbus.UInt32(1),dbus.UInt32(1399999999)):
                log.debug("Got fact %s between %s and %s" % (f['id'], f['start_time'], f['end_time']))
                self.events[str(f['id'])] = f
        else:
            raise Exceptions.RefreshError("Hamster not available")
                
    def get(self, uri):
        log.debug("get(%s)" % uri)
        DataProvider.TwoWay.get(self, uri)
        conduitEvent = Event.Event()
        conduitEvent.set_from_ical_string(self._get_event(uri))
        conduitEvent.set_mtime(self._get_event_mtime(uri))
        conduitEvent.set_UID(uri)
        conduitEvent.set_open_URI(uri)
        return conduitEvent
                
    def get_all(self):
        log.debug("get(all)")
        DataProvider.TwoWay.get_all(self)
        return self.events.keys()

    #def put(self, note, overwrite, LUID=None):
    #    """
    #    Stores a Note in Tomboy.
    #    """
    #    DataProvider.TwoWay.put(self, note, overwrite, LUID)
    #    log.debug("Put note LUID: %s" % LUID)

    #    #Check if the note, or one with same title exists
    #    existingNote = None
    #    if LUID != None:
    #        if self.remoteTomboy.NoteExists(LUID):
    #            existingNote = self._get_note(LUID)
    #    else:
    #        LUID = self.remoteTomboy.FindNote(note.get_title())
    #        if LUID != "":
    #            existingNote = self._get_note(str(LUID))

    #    #compare with the existing note
    #    if existingNote != None:
    #        comp = note.compare(existingNote)
    #        log.debug("Comparing new %s with existing %s" % (note.get_title(),existingNote.get_title()))
    #        if comp == conduit.datatypes.COMPARISON_EQUAL:
    #            log.info("Notes are equal")
    #        elif overwrite == True or comp == conduit.datatypes.COMPARISON_NEWER:
    #            log.info("Updating note")
    #            self._update_note(LUID, note)
    #        else:
    #            raise Exceptions.SynchronizeConflictError(comp, note, existingNote)
    #    else:                    
    #        log.info("Saving new Note")
    #        LUID = self._create_note(note)

    #    return self.get(LUID).get_rid()

#    def delete(self, LUID):
#        if self.remoteTomboy.NoteExists(LUID):
#            if self.remoteTomboy.DeleteNote(LUID):
#                log.debug("Deleted note %s" % LUID)
#                return
#
#        log.warn("Error deleting note %s" % LUID)

    def finish(self, aborted, error, conflict):
        DataProvider.TwoWay.finish(self)
        self.events = {}

    def get_UID(self):
        return Utils.get_user_string()


