#
#  $Id: Mail.py,v 1.2 1999/12/11 12:35:11 rob Exp $
#
#  Copyright 1999 Rob Tillotson <robt@debian.org>
#  All Rights Reserved
#
#  Permission to use, copy, modify, and distribute this software and
#  its documentation for any purpose and without fee or royalty is
#  hereby granted, provided that the above copyright notice appear in
#  all copies and that both the copyright notice and this permission
#  notice appear in supporting documentation or portions thereof,
#  including modifications, that you you make.
#
#  THE AUTHOR ROB TILLOTSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
#  THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
#  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
#  RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
#  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
#  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE!
#
"""Mail.
"""

__version__ = '$Id: Mail.py,v 1.2 1999/12/11 12:35:11 rob Exp $'

__copyright__ = 'Copyright 1999 Rob Tillotson <robt@debian.org>'


# prefs:
#   creator 'mail'
#   id 1: local sync prefs
#   id 2: remote sync prefs
#   id 3: signature
#   always backup = 1


import string, struct

import Pyrite
import Pyrite.Connector

from Pyrite import FLD_BOOLEAN, FLD_INT, FLD_STRING, FLD_TIME_T, _
from Pyrite import Blocks

class Connector(Pyrite.Connector.Connector):
    name = 'Mail'
    version = Pyrite.version
    author = Pyrite.author
    url = ''
    description = _("The built-in mail application.")

    def __init__(self, *a, **kw):
	apply(Pyrite.Connector.Connector.__init__, (self,)+a, kw)
	self.default_name = 'MailDB'
	self.default_class = Database
	self.default_creator = 'mail'
	self.default_type = 'DATA'
	self.pref_map = {
	    1: SyncPref,
	    2: SyncPref,
	    3: SignaturePref,
	    }
	
    def classify(self, info={}):
	if info.get('type') == 'DATA' and info.get('creator') == 'mail':
	    return Database

class Record(Blocks.Record):
    def __init__(self, *a, **kw):
	self.fields = {
	    'read': (FLD_BOOLEAN, 0),
	    'signature': (FLD_BOOLEAN, 0),
	    'confirmRead': (FLD_BOOLEAN, 0),
	    'confirmDelivery': (FLD_BOOLEAN, 0),
	    'priority': (FLD_INT, 0),
	    'addressing': (FLD_INT, 0),
	    'dated': (FLD_BOOLEAN, 0),
	    'date': (FLD_TIME_T, (0,0,0,0,0,0,0,0,0,0)),
	    'subject': (FLD_STRING, ''),
	    'from': (FLD_STRING, ''),
	    'to': (FLD_STRING, ''),
	    'cc': (FLD_STRING, ''),
	    'bcc': (FLD_STRING, ''),
	    'replyTo': (FLD_STRING, ''),
	    'sentTo': (FLD_STRING, ''),
	    'body': (FLD_STRING, ''),
	    }
	apply(Pyrite.Record.__init__, (self,)+a, kw)

    def unpack(self, raw):
	self.raw = raw

	d, h, m, flags = struct.unpack('>HBBBx', raw[:6])
	self.data['date'] = Blocks.palm_date_to_tuple(d, h, m)
	if d: self.data['dated'] = 1
	else: self.data['dated'] = 0

	if flags & 0x80: self.data['read'] = 1
	if flags & 0x40: self.data['signature'] = 1
	if flags & 0x20: self.data['confirmRead'] = 1
	if flags & 0x10: self.data['confirmDelivery'] = 1
	self.data['priority'] = (flags & 0x0c) >> 2
	self.data['addressing'] = (flags & 0x03)

	for f, v in map(None, ['subject','from','to','cc','bcc','replyTo',
			       'sentTo','body'],
			string.split(raw[6:], '\0')):
	    if f:
		if v: self.data[f] = v
		else: self.data[f] = ''
	    
	
    def pack(self):
	if self.data['dated']:
	    d = Blocks.tuple_to_palm_date(self.data['date'])
	    h = self.data['date'][3]
	    m = self.data['date'][4]
	else:
	    d = 0
	    h = 0
	    m = 0

	flags = 0
	if self.data['read']: flags = flags | 0x80
	if self.data['signature']: flags = flags | 0x40
	if self.data['confirmRead']: flags = flags | 0x20
	if self.data['confirmDelivery']: flags = flags | 0x10
	flags = flags | (self.data['priority'] & 0x03) << 2
	flags = flags | (self.data['addressing'] & 0x03)

	raw = struct.pack('>HBBBB', d, h, m, flags, 0)
	
	for f in ['subject','from','to','cc','bcc','replyTo',
		  'sentTo','body']:
	    if self.data[f]: raw = raw + self.data[f] + '\0'
	    else: raw = raw + '\0'

	self.raw = raw
	return raw

class SignaturePref(Blocks.PrefBlock):
    def __init__(self, *a, **kw):
	self.fields = {
	    'signature': (FLD_STRING, '')
	    }
	apply(Blocks.PrefBlock.__init__, (self,)+a, kw)

    def unpack(self, raw):
	self.raw = raw
	self.data['signature'] = string.split(raw, '\0', 1)[0]

    def pack(self):
	raw = self.data['signature'] + '\0'
	return raw


class SyncPref(Blocks.PrefBlock):
    def __init__(self, *a, **kw):
	self.fields = {
	    'syncType': (FLD_INT, 0),
	    'getHigh': (FLD_BOOLEAN, 0),
	    'getContaining': (FLD_BOOLEAN, 0),
	    'truncate': (FLD_INT, 0),
	    'filterTo': (FLD_STRING, ''),
	    'filterFrom': (FLD_STRING, ''),
	    'filterSubject': (FLD_STRING, ''),
	    }
	apply(Blocks.PrefBlock.__init__, (self,)+a, kw)

    def unpack(self, raw):
	self.raw = raw

	st, gh, gc, trunc = struct.unpack('>BBBxH', raw[:6])
	self.data['syncType'] = st
	self.data['getHigh'] = gh
	self.data['getContaining'] = gc
	self.data['truncate'] = trunc

	self.data['filterTo'], raw = string.split(raw[6:], '\0', 1)
	self.data['filterFrom'], raw = string.split(raw, '\0', 1)
	self.data['filterSubject'] = string.split(raw, '\0', 1)[0]

    def pack(self):
	raw = struct.pack('>BBBBH',
			  self.data['syncType'],
			  self.data['getHigh'],
			  self.data['getContaining'],
			  0,
			  self.data['truncate'])
	raw = raw + self.data['filterTo'] + '\0'
	raw = raw + self.data['filterFrom'] + '\0'
	raw = raw + self.data['filterSubject'] + '\0'
	self.raw = raw
	return raw
			  

class Database(Pyrite.Database):
    def __init__(self, *a, **kw):
	apply(Pyrite.Database.__init__, (self,)+a, kw)
	self.record_class = Record
	#self.appblock_class = AppBlock
