"""IC wrapper module, based on Internet Config 1.3"""

import icglue
import string
import sys
import os
from Carbon import Res
import Carbon.File
import macostools

error=icglue.error

# From ictypes.h:
icPrefNotFoundErr = -666        # preference not found (duh!)
icPermErr = -667                # cannot set preference
icPrefDataErr = -668            # problem with preference data
icInternalErr = -669            # hmm, this is not good
icTruncatedErr = -670           # more data was present than was returned
icNoMoreWritersErr = -671       # you cannot begin a write session because someone else is already doing it */
icNothingToOverrideErr = -672   # no component for the override component to capture
icNoURLErr = -673               # no URL found
icConfigNotFoundErr = -674      # no configuration was found
icConfigInappropriateErr = -675 # incorrect manufacturer code

ICattr_no_change = -1

icNoPerm = 0
icReadOnlyPerm = 1
icReadWritePerm = 2
# End of ictypes.h

class ICOpaqueData:
    """An unparseable IC entry"""
    def __init__(self, data):
        self.data = data

    def __repr__(self):
        return "ICOpaqueData(%r)"%(self.data,)

_ICOpaqueDataType=type(ICOpaqueData(''))

def _decode_default(data, key):
    if len(data) == 0:
        return data
    if ord(data[0]) == len(data)-1:
        # Assume Pstring
        return data[1:]
    return ICOpaqueData(data)


def _decode_multistr(data, key):
    numstr = ord(data[0]) << 8 | ord(data[1])
    rv = []
    ptr = 2
    for i in range(numstr):
        strlen = ord(data[ptr])
        str = data[ptr+1:ptr+strlen+1]
        rv.append(str)
        ptr = ptr + strlen + 1
    return rv

def _decode_fontrecord(data, key):
    size = ord(data[0]) << 8 | ord(data[1])
    face = ord(data[2])
    namelen = ord(data[4])
    return size, face, data[5:5+namelen]

def _decode_boolean(data, key):
    return ord(data[0])

def _decode_text(data, key):
    return data

def _decode_charset(data, key):
    return data[:256], data[256:]

def _decode_appspec(data, key):
    namelen = ord(data[4])
    return data[0:4], data[5:5+namelen]

def _code_default(data, key):
    return chr(len(data)) + data

def _code_multistr(data, key):
    numstr = len(data)
    rv = chr((numstr>>8) & 0xff) + chr(numstr & 0xff)
    for i in data:
        rv = rv + _code_default(i)
    return rv

def _code_fontrecord(data, key):
    size, face, name = data
    return chr((size>>8) & 0xff) + chr(size & 0xff) + chr(face & 0xff) + \
        chr(0) + _code_default(name)

def _code_boolean(data, key):
    print 'XXXX boolean:', repr(data)
    return chr(data)

def _code_text(data, key):
    return data

def _code_charset(data, key):
    return data[0] + data[1]

def _code_appspec(data, key):
    return data[0] + _code_default(data[1])

_decoder_table = {
    "ArchieAll" : (_decode_multistr , _code_multistr),
    "UMichAll" : (_decode_multistr , _code_multistr),
    "InfoMacAll" : (_decode_multistr , _code_multistr),
    "ListFont" : (_decode_fontrecord , _code_fontrecord),
    "ScreenFont" : (_decode_fontrecord , _code_fontrecord),
    "PrinterFont" : (_decode_fontrecord , _code_fontrecord),
#   "DownloadFolder" : (_decode_filespec , _code_filespec),
    "Signature": (_decode_text , _code_text),
    "Plan" : (_decode_text , _code_text),
    "MailHeaders" : (_decode_text , _code_text),
    "NewsHeaders" : (_decode_text , _code_text),
#   "Mapping"
    "CharacterSet" : (_decode_charset , _code_charset),
    "Helper\245" : (_decode_appspec , _code_appspec),
#   "Services" : (_decode_services, ????),
    "NewMailFlashIcon" : (_decode_boolean , _code_boolean),
    "NewMailDialog" : (_decode_boolean , _code_boolean),
    "NewMailPlaySound" : (_decode_boolean , _code_boolean),
#   "WebBackgroundColor" : _decode_color,
    "NoProxyDomains" : (_decode_multistr , _code_multistr),
    "UseHTTPProxy" : (_decode_boolean , _code_boolean),
    "UseGopherProxy": (_decode_boolean , _code_boolean),
    "UseFTPProxy" : (_decode_boolean , _code_boolean),
    "UsePassiveFTP" : (_decode_boolean , _code_boolean),
}

def _decode(data, key):
    if '\245' in key:
        key2 = key[:string.index(key, '\245')+1]
    else:
        key2 = key
    if _decoder_table.has_key(key2):
        decoder = _decoder_table[key2][0]
    else:
        decoder = _decode_default
    return decoder(data, key)

def _code(data, key):
    if type(data) == _ICOpaqueDataType:
        return data.data
    if '\245' in key:
        key2 = key[:string.index(key, '\245')+1]
    else:
        key2 = key
    if _decoder_table.has_key(key2):
        coder = _decoder_table[key2][1]
    else:
        coder = _code_default
    return coder(data, key)

class IC:
    def __init__(self, signature='Pyth', ic=None):
        if ic:
            self.ic = ic
        else:
            self.ic = icglue.ICStart(signature)
            if hasattr(self.ic, 'ICFindConfigFile'):
                self.ic.ICFindConfigFile()
        self.h = Res.Resource('')

    def keys(self):
        rv = []
        self.ic.ICBegin(icReadOnlyPerm)
        num = self.ic.ICCountPref()
        for i in range(num):
            rv.append(self.ic.ICGetIndPref(i+1))
        self.ic.ICEnd()
        return rv

    def has_key(self, key):
        return self.__contains__(key)

    def __contains__(self, key):
        try:
            dummy = self.ic.ICFindPrefHandle(key, self.h)
        except icglue.error:
            return 0
        return 1

    def __getitem__(self, key):
        attr = self.ic.ICFindPrefHandle(key, self.h)
        return _decode(self.h.data, key)

    def __setitem__(self, key, value):
        value = _code(value, key)
        self.ic.ICSetPref(key, ICattr_no_change, value)

    def launchurl(self, url, hint=""):
        # Work around a bug in ICLaunchURL: file:/foo does
        # not work but file:///foo does.
        if url[:6] == 'file:/' and url[6] != '/':
            url = 'file:///' + url[6:]
        self.ic.ICLaunchURL(hint, url, 0, len(url))

    def parseurl(self, data, start=None, end=None, hint=""):
        if start == None:
            selStart = 0
            selEnd = len(data)
        else:
            selStart = selEnd = start
        if end != None:
            selEnd = end
        selStart, selEnd = self.ic.ICParseURL(hint, data, selStart, selEnd, self.h)
        return self.h.data, selStart, selEnd

    def mapfile(self, file):
        if type(file) != type(''):
            file = file.as_tuple()[2]
        return self.ic.ICMapFilename(file)

    def maptypecreator(self, type, creator, filename=""):
        return self.ic.ICMapTypeCreator(type, creator, filename)

    def settypecreator(self, file):
        file = Carbon.File.pathname(file)
        record = self.mapfile(os.path.split(file)[1])
        MacOS.SetCreatorAndType(file, record[2], record[1])
        macostools.touched(fss)

# Convenience routines
_dft_ic = None

def launchurl(url, hint=""):
    global _dft_ic
    if _dft_ic == None: _dft_ic = IC()
    return _dft_ic.launchurl(url, hint)

def parseurl(data, start=None, end=None, hint=""):
    global _dft_ic
    if _dft_ic == None: _dft_ic = IC()
    return _dft_ic.parseurl(data, start, end, hint)

def mapfile(filename):
    global _dft_ic
    if _dft_ic == None: _dft_ic = IC()
    return _dft_ic.mapfile(filename)

def maptypecreator(type, creator, filename=""):
    global _dft_ic
    if _dft_ic == None: _dft_ic = IC()
    return _dft_ic.maptypecreator(type, creator, filename)

def settypecreator(file):
    global _dft_ic
    if _dft_ic == None: _dft_ic = IC()
    return _dft_ic.settypecreator(file)

def _test():
    ic = IC()
    for k in ic.keys():
        try:
            v = ic[k]
        except error:
            v = '????'
        print k, '\t', v
    sys.exit(1)

if __name__ == '__main__':
    _test()
