#!/usr/bin/env python
from gtk import *
from gnome.ui import *
import sys
import string
import os, os.path
import ConfigParser, gettext

import utils, config

gettext.bindtextdomain('gtex-letter', '/usr/share/locale')
gettext.textdomain('gtex-letter')
_ = gettext.gettext

debug = 0

VCARD_ARG_ID = 0
VCARD_ARG_ADR_POST_OFFICE = 0
VCARD_ARG_ADR_EXTENDED = 1
VCARD_ARG_ADR_STREET = 2
VCARD_ARG_ADR_CITY = 3
VCARD_ARG_ADR_REGION = 4
VCARD_ARG_ADR_ZIP = 5
VCARD_ARG_ADR_COUNTRY = 6
VCARD_ARG_NAME_LASTNAME = 0
VCARD_ARG_NAME_FIRSTNAME = 1
VCARD_ARG_NAME_MIDDLENAME = 2
VCARD_ARG_NAME_NAME_PREFIX = 3
VCARD_ARG_NAME_NAME_SUFFIX = 4
VCARD_ARG_TEL = 0

VCARD_LINE_IDENT_ID = 'FN'
VCARD_LINE_IDENT_NAME = 'N'
VCARD_LINE_IDENT_ADDRESS = 'ADR'
VCARD_LINE_IDENT_TELEPHONE = 'TEL'

WINDOW_TITLE = 'Addressbook'

PRG_DIR='' # is set by calling programm (so do i hope... :)


def get_vcard_argument(entry, num_arg):
	# get the argument nr. 'num_arg' in a vcard-line
	# ex: ADR:;Postfach;Leberngasse 17;Olten;;4601
	# here, num_arg 3 means Olten. (num_arg 0 is empty)
	
	start = string.find(entry, ':')+1
	arg = ""
	for i in range(0, num_arg+1):
		end = string.find(entry, ';', start)
		if end == -1:
			end = len(entry)
		arg = string.rstrip(entry[start: end])
		start = end+1
	return arg

class addresscard:
	def __init__ (self):
		self.id = ""
		self.name_prefix = ""
		self.firstname = ""
		self.middlename = ""
		self.lastname = ""
		self.name_suffix = ""
		self.post_office = ""
		self.extended = ""
		self.street = ""
		self.zip = ""
		self.city = ""
		self.region = ""
		self.country = ""
		self.telephone = ""
	def set_id(self, entry):
		self.id=get_vcard_argument(entry, VCARD_ARG_ID)
		if debug:
			print _("Set id to:"), self.id
	def set_name(self, entry):
		get = get_vcard_argument
		self.name_prefix = get(entry, VCARD_ARG_NAME_NAME_PREFIX)
		self.lastname = get(entry, VCARD_ARG_NAME_LASTNAME)
		self.middlename = get(entry, VCARD_ARG_NAME_MIDDLENAME)
		self.firstname = get(entry, VCARD_ARG_NAME_FIRSTNAME)
		self.name_suffix = get(entry, VCARD_ARG_NAME_NAME_SUFFIX)
		if debug:
			print _("Set prefix firstname middlename lastname suffix to:"), self.name_prefix,  self.firstname, self.middlename, self.lastname, self.name_suffix
	
	def set_address (self, entry):
		get = get_vcard_argument
		self.post_office = get(entry, VCARD_ARG_ADR_POST_OFFICE)
		self.extension = get(entry, VCARD_ARG_ADR_EXTENDED)
		self.street= get(entry, VCARD_ARG_ADR_STREET)
		self.zip= get(entry, VCARD_ARG_ADR_ZIP)
		self.city= get(entry, VCARD_ARG_ADR_CITY)
		self.region= get(entry, VCARD_ARG_ADR_REGION)
		self.country= get(entry, VCARD_ARG_ADR_COUNTRY)
		if debug:
			print _("Set address to:") , self.post_office, self.extended, self.street , self.zip , self.city, self.region, self.country
	def set_telephone(self, entry):
		if not self.telephone: # we take the first phone number and skip the remaining ones
			self.telephone=get_vcard_argument(entry, VCARD_ARG_TEL)
			if debug:
				print _("Set telephone to:"), self.telephone
	
	def check_for_address(self):
		return self.get_extended() or self.get_post_office() or \
			self.get_region() or self.get_street() or \
			self.get_zip() or self.get_city() or \
			self.get_country() or self.get_telephone()
	def get_by_name(self, name):
		if name == 'id': return self.get_id()
		elif name == 'name_prefix': return self.get_name_prefix()
		elif name == 'firstname': return self.get_firstname()
		elif name == 'middlename': return self.get_middlename()
		elif name == 'lastname': return self.get_lastname()
		elif name == 'name_suffix': return self.get_name_suffix()
		elif name == 'extended': return self.get_extended()
		elif name == 'post_office': return self.get_post_office()
		elif name == 'street': return self.get_street()
		elif name == 'zip': return self.get_zip()
		elif name == 'city': return self.get_city()
		elif name == 'region': return self.get_region()
		elif name == 'country': return self.get_country()
		else:
			print _('Error: Could not get address-card-attribute:'), name
	def get_id(self):
		return self.id
	def get_name_prefix(self):
		return self.name_prefix
	def get_name_suffix(self):
		return self.name_suffix
	def get_firstname(self):
		return self.firstname
	def get_middlename(self):
		return self.middlename
	def get_lastname(self):
		return self.lastname
	def get_extended(self):
		return self.extended
	def get_post_office(self):
		return self.post_office
	def get_region(self):
		return self.region
	def get_street(self):
		return self.street
	def get_zip(self):
		return self.zip
	def get_city(self):
		return self.city
	def get_country(self):
		return self.country
	def get_telephone(self):
		return self.telephone
	
	def print_card(self, addressformats):
		print _('ID:'), self.get_id()
		print utils.mk_adr(self, addressformats),
		print _('Phone:') + self.get_telephone()
		
def key_match(line, key):
	return line[0:len(key)] == key
def value(line, key):
	return line[len(key):-1]

class addressbook:

	def __init__ (self, addressbooks=[], column_widths='', columns=''):
		self.addressbooks = addressbooks

		self.addressbook_column_widths = column_widths
		self.addressbook_columns = columns

		self.address_cards = []
		
	def print_ab (self, addressformats):
		for i in self.address_cards:
			i.print_card(addressformats)
		
	def get_card(self, id):
		for i in self.address_cards:
			if i.get_id() == id:
				return i

	def read_file (self):
		def read_card(self, file):
			ac = addresscard()
			while 1:
				line = file.readline()
				if not line or key_match(line, "END:VCARD"):
					break
				if key_match(line, VCARD_LINE_IDENT_ID):
					ac.set_id(line)
				if key_match(line, VCARD_LINE_IDENT_NAME):
					ac.set_name(line)
				if key_match(line, VCARD_LINE_IDENT_ADDRESS):
					ac.set_address(line)
				if key_match(line, VCARD_LINE_IDENT_TELEPHONE):
					ac.set_telephone(line)
			return ac
		for file in self.addressbooks:
			old = file
			file = utils.get_path(file)
			if file:
				file = open (file, 'r+')
				while 1:
					line = file.readline()
					if not line:
						break
					if key_match(line, "BEGIN:VCARD"):
						card = read_card(self, file)
						if card.check_for_address(): # we just take the ones with a real postal address
							self.address_cards.append(card)
			else:
				print _("Error: Could not find addressbook:"), old
			
	
	def show(self):
		s = []
		def delete_event(win, event=None, s=s):
			win.destroy()
			mainquit()
		def win_close(win):
			win.destroy()
		win = GtkWindow()
		win.set_title(WINDOW_TITLE)
		
		box1 = GtkVBox()
		win.add(box1)
		box1.show()

		column_widths = ['0'] + string.split(self.addressbook_column_widths, ',')
		column_names = ['id'] + string.split(self.addressbook_columns, ',')
		
		# The number of columns is determinded by the number of widths for columns in the rc file
		count = len(column_widths)
		
		if count <> len(column_names):
			print _("Error: Not the same number of column_widths and column_names provided in the rc-file")
		for i in range(count):
			column_widths[i]=string.atoi(string.strip(column_widths[i]))
		for i in range(count):
			column_names[i] = ' ' + string.strip(column_names[i])
		
		clist = GtkCList(count, column_names)
		clist.set_column_visibility(0, FALSE) # hide id
		clist.sorting=[]
		for i in range(count):
			clist.sorting.append(SORT_ASCENDING)

		clist.set_column_width(0, 20)
		for i in range(1, count):
			clist.set_column_width(i, column_widths[i])
		column_names[0]='id'
		for i in range(1, count):
			column_names[i]=string.lower(string.strip(column_names[i]))

		def fill_list(cards, columns=column_names, clist=clist):
			for i in cards:
				values=[]
				for column in columns:
					
					if column == 'id':
						values.append(i.get_id())
					elif column == 'name_prefix':
						values.append(i.get_name_prefix())
					elif column == 'firstname':
						values.append(i.get_firstname())
					elif column == 'lastname':
						values.append(i.get_lastname())
					elif column == 'extended':
						values.append(i.get_extended())
					elif column == 'street':
						values.append(i.get_street())
					elif column == 'zip':
						values.append(i.get_zip())
					elif column == 'city':
						values.append(i.get_city())
					elif column == 'country':
						values.append(i.get_country())
					elif column == 'telephone':
						values.append(i.get_telephone())
				clist.append(values)
		

		def select_clist(_clist, r, c, event, cards=self.address_cards, selected=s):
			if c >= 0 and r >= 0:
				selected.append( _clist.get_text(r, 0))
		def unselect_clist(_clist, r, c, event, cards=self.address_cards, selected=s):
			if c >= 0 and r >= 0:
				key = _clist.get_text(r, 0)
				if key in selected:
					selected.remove( key )

		def click_title(_clist, c, sorting = clist.sorting, cards=self.address_cards, fill_list=fill_list):

			sorting[c]=  not sorting[c]
			if debug:
				print _('Sorting:'), sorting

			_clist.set_sort_type(sorting[c])

			_clist.set_sort_column(c)
			_clist.sort()
			
		def doubleclick(_clist, _button, win_close=win_close, win=win):
			if _button.type==5:
				win_close(win)
				mainquit()
		
		def click_ok(_button, cards=self.address_cards, s=s, win_close=win_close, win=win, clist=clist):
			win_close(win)
			mainquit()
		def click_cancel(_button, cards=self.address_cards, win_close=win_close, win=win, s=s):
			for i in range(len(s)):
				s.remove(s[0])
			win_close(win)
			mainquit()
		
		box2 = GtkVBox(spacing=10)
		box2.set_border_width(10)
		box1.pack_start(box2)
		box2.show()
		
		clist.connect("select_row", select_clist)
		clist.connect("unselect_row", unselect_clist)
		clist.connect("click_column", click_title)
		clist.connect("button_press_event", doubleclick)
		clist.set_selection_mode(SELECTION_MULTIPLE)
		

		
		fill_list(self.address_cards)

		clist.set_border_width(5)

		swin = GtkScrolledWindow()
		swin.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
		box2.pack_start(swin)
		swin.show()

		swin.add(clist)
		total_column_width=0
		for i in column_widths:
			total_column_width = total_column_width + i
		swin.set_usize(total_column_width, 400)
		clist.show()
		
		separator = GtkHSeparator()
		box1.pack_start(separator, expand=FALSE)
		separator.show()

		box2 = GtkVBox(spacing=10)
		box2.set_border_width(10)
		box1.pack_start(box2, expand=FALSE)
		box2.show()

		box1 = GtkHBox(spacing=10)
		button = GtkButton("ok")
		button.connect("clicked", click_ok)
		box1.pack_start(button)
		button.set_flags(CAN_DEFAULT)
		button.grab_default()
		button.show()

		button = GtkButton("cancel")
		button.connect("clicked", click_cancel)
		box1.pack_start(button)
		button.set_flags(CAN_DEFAULT)
		button.grab_default()
		button.show()
		
		box2.pack_start(box1, expand=FALSE)
		box1.show()

		win.connect("destroy", win_close)
		win.connect("delete_event", delete_event)
		win.set_usize(total_column_width + count*8 + 50, 500)
		win.show()
		
		mainloop()
		
		if s:
			return s
		else:
			return None

def init_addressbooks(rc, rc_key, texts):
	def_str = utils.rc_set('MAIN', rc_key, rc)
	def stripmarks(str):
		if str[0] == "'" or str[0] == "\"":
			str = str [1:]
		if str[-1] == "'" or str[-1] == "\"":
			str = str [:-1]
		return str
	if def_str:
		num = 1
		while num >0:
			num = string.find(def_str, ";")
			if num >0:
				tmpstr=stripmarks(string.strip(def_str[0:num]))
				texts.append (tmpstr)
				def_str= def_str[num+2:]
			else:
				tmpstr=stripmarks(string.strip(def_str))
				texts.append(tmpstr)
	if texts == []:
		print error_txt


def main():
	file = utils.get_path('.gtex-letterrc', '')
	rc = config.gtex_letter_config(file)

	ab = addressbook(rc.addressbooks, rc.addressbook_column_widths, rc.addressbook_columns)
	ab.read_file ()
	s = ab.show()
	if s:
		for a in s:
			if len(s) > 1:
				print 
				print _("New address:")
			ac = ab.get_card(a)
			ac.print_card(rc.addressformats)
	else:
		print _("Nothing selected.")

if __name__ == '__main__':
       main ()

