#FIXME: Proper license and attribution
#Most code adapted from gammu (GPL2) and phonetooth (GPL2)

import os
import bluetooth
import logging
import vobject
log = logging.getLogger("modules.Phone")

import conduit
import conduit.dataproviders.DataProvider as DataProvider
import conduit.datatypes.Contact as Contact
import conduit.datatypes.Event as Event
import conduit.utils as Utils
#import ScanThreads
#import Data


MODULES = {}

try:
    import gammu
    log.info("Module Information: %s" % Utils.get_module_information(gammu, "__version__"))
    GAMMU_SUPPORTED = True
    MODULES = {
        "GammuContactTwoWay"  : { "type": "dataprovider" },
        "GammuCalendarTwoWay"  : { "type": "dataprovider" },
    }
except ImportError:
    log.info("Gammu based phone support disabled")
    GAMMU_SUPPORTED = False



class GammuContactTwoWay(DataProvider.TwoWay):
    
    connection_name = ""
    memory_loc = "ME"

    _configurable_ = True
    


    _name_ = "Gammu Phone Contacts"
    _description_ = "Synchronizes mobile phone contacts"
    _category_ = conduit.dataproviders.CATEGORY_OFFICE
    _module_type_ = "twoway"
    _in_type_ = "contact"
    _out_type_ = "contact"
    _icon_ = "applications-internet"


    def configure(self, window):
        import gtk
        widget = Utils.dataprovider_glade_get_widget(
                        __file__, 
                        "config.glade",
                        "GammuConfigDialog"
                        )
        
        #get a whole bunch of widgets
        sourceTextBox = widget.get_widget("entry1")
        sourceComboBox = widget.get_widget("combobox1")
        self.get_configuration()

        sourceTextBox.set_text(self.connection_name)
        sourceComboBox.set_active(0)

        dlg = widget.get_widget("GammuConfigDialog")
        response = Utils.run_dialog(dlg, window)
        if response == True:
            self._set_connection_name(sourceTextBox.get_text())
            self._set_memory(sourceComboBox.get_active_text())
        dlg.destroy()    

       
    def _set_connection_name(self, connection_name):
        self.connection_name = connection_name

    def _set_memory(self, memory_loc_long):
        if memory_loc_long == 'Phone Memory':
            self.memory_loc = 'ME'
        if memory_loc_long == 'Sim Card':
            self.memory_loc = 'SM'

    def start_connection(self):
        self.sm = gammu.Core.StateMachine()
        self.sm.SetConfig(0, {
	    'StartInfo': 'no', 
	    'UseGlobalDebugFile': 0, 
	    'DebugFile': '', 
	    'SyncTime': 'no', 
	    'Connection': 'at', 
            'LockDevice': 'no', 
	    'DebugLevel': '', 
	    'Device': self.connection_name, 
	    'Localize': None, 
	    'Model': ''
        })
        try:
            self.sm.Init()
        except:
            print "is phone connected?"

    def refresh(self):
        DataProvider.TwoWay.refresh(self)
        try:
            self.end_connection()
        except:
            print 'error'

    def get_all(self):
        self.start_connection()
        location = self.memory_loc
        self.luidDictionary = {}
        luidList = []
        
        status = self.sm.GetMemoryStatus(Type=location)
        remain = status['Used']
        log.debug("%s contacts on phone" % remain)

        start = True
        while remain > 0:
            if start:
                entry = self.sm.GetNextMemory(Start=True, Type = location)
                start = False
            else:
                entry = self.sm.GetNextMemory(Location=entry['Location'], Type = location)
            remain = remain - 1
            contact_luid = str(entry['Entries'][len(entry['Entries'])-1]['Value'])
            self.luidDictionary[contact_luid] = entry['Location']
            luidList.append(contact_luid)
    
        #self.end_connection()
        return luidList

    def get(self, LUID):
        #self.start_connection()
        entry = self.sm.GetMemory(Location = self.luidDictionary[LUID], Type = self.memory_loc)
        phonecontact = vobject.readOne(gammu.Core.EncodeVCARD(entry))
        contact = Contact.Contact(vcard = phonecontact)
        contact.set_UID(LUID)
        return contact

    def get_configuration(self):
        return {
            "connection_name" : self.connection_name, 
            "memory_loc" : self.memory_loc
        }

    def get_UID(self):
        return "GammuPhone"


    def end_connection(self):
        self.sm.Terminate()

class GammuCalendarTwoWay(DataProvider.TwoWay):
    
    connection_name = ""
    memory_loc = "ME"

    _configurable_ = True

    _name_ = "Gammu Phone Calendar"
    _description_ = "Synchronizes mobile phone calendars"
    _category_ = conduit.dataproviders.CATEGORY_OFFICE
    _module_type_ = "twoway"
    _in_type_ = "event"
    _out_type_ = "event"
    _icon_ = "applications-internet"


    def configure(self, window):
        import gtk
        widget = Utils.dataprovider_glade_get_widget(
                        __file__, 
                        "config.glade",
                        "GammuConfigDialog"
                        )
        
        #get a whole bunch of widgets
        sourceTextBox = widget.get_widget("entry1")
        sourceComboBox = widget.get_widget("combobox1")
        self.get_configuration()

        sourceTextBox.set_text(self.connection_name)
        sourceComboBox.set_active(0)

        dlg = widget.get_widget("GammuConfigDialog")
        response = Utils.run_dialog(dlg, window)
        if response == True:
            self._set_connection_name(sourceTextBox.get_text())
            self._set_memory(sourceComboBox.get_active_text())
        dlg.destroy()    

       
    def _set_connection_name(self, connection_name):
        self.connection_name = connection_name

    def _set_memory(self, memory_loc_long):
        if memory_loc_long == 'Phone Memory':
            self.memory_loc = 'ME'
        if memory_loc_long == 'Sim Card':
            self.memory_loc = 'SM'

    def start_connection(self):
        self.sm = gammu.Core.StateMachine()
        self.sm.SetConfig(0, {
	    'StartInfo': 'no', 
	    'UseGlobalDebugFile': 0, 
	    'DebugFile': '', 
	    'SyncTime': 'no', 
	    'Connection': 'at', 
            'LockDevice': 'no', 
	    'DebugLevel': '', 
	    'Device': self.connection_name, 
	    'Localize': None, 
	    'Model': ''
        })
        try:
            self.sm.Init()
        except:
            print "is phone connected?"

    def refresh(self):
        DataProvider.TwoWay.refresh(self)
        try:
            self.end_connection()
        except:
            print 'error'

    def get_all(self):
        self.start_connection()
        location = self.memory_loc
        self.luidDictionary = {}
        luidList = []
        
        status = self.sm.GetCalendarStatus()
        remain = status['Used']
        log.debug("%s contacts on phone" % remain)

        start = True
        while remain > 0:
            if start:
                entry = self.sm.GetNextCalendar(Start=True)
                start = False
            else:
                entry = self.sm.GetNextCalendar(Location=entry['Location'])
            remain = remain - 1
            contact_luid = str(entry['Entries'][len(entry['Entries'])-1]['Value'])
            self.luidDictionary[contact_luid] = entry['Location']
            luidList.append(contact_luid)
        #self.end_connection()
        return luidList

    def get(self, LUID):
        #self.start_connection()
        entry = self.sm.GetCalendar(Location = self.luidDictionary[LUID])
        readable_format = {}
        emails = 0
        cal = vobject.iCalendar()
        cal.add('vevent')
        for v in entry['Entries']:
            if v['Type'] == 'START_DATETIME':
                cal.vevent.add('dtstart').value = v['Value']
            if v['Type'] == 'END_DATETIME':
                cal.vevent.add('dtend').value = v['Value']
            if v['Type'] == 'TEXT':
                cal.vevent.add('summary').value = str(v['Value'])
            if v['Type'] == 'LOCATION':
                cal.vevent.add('location').value = str(v['Value'])
            if v['Type'] == 'LAST_MODIFIED':
                cal.vevent.add('last-modified').value = v['Value']
                event_mtime = v['Value']

        print cal
        event = Event.Event()
        event.set_from_ical_string(cal.serialize())
        event.set_UID(LUID)
        event.set_mtime(event_mtime)
        return event


    def get_configuration(self):
        return {
            "connection_name" : self.connection_name, 
            "memory_loc" : self.memory_loc
        }

    def get_UID(self):
        return "GammuPhone"


    def end_connection(self):
        self.sm.Terminate()

