#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, getopt
import cPickle as pickle

g_verbose = False

class VCardContact:
    def __init__( self ):
        self.fn = ""
        # dict with {type, number}
        self.tel = {}

    def reset( self ):
        self.fn = ""
        self.tel.clear()

    def setName( self, name ):
        self.fn = name.strip('\r\n') 

    def addPhoneNumber( self, type, number ):
        self.tel[ type ] = number.strip('\r\n') 

    def to_list( self ):
        """ return a list of entries for FN and numbers """
        phone_list = []
        for e,v in self.tel.iteritems():
            try:
                u_nam_typ = unicode(self.fn + ' ' + e, encoding="utf-8", errors='replace' )
                phone_list.append( [ u_nam_typ ,unicode(v)] )
            except:
                print "Error appending entry for ", self.fn, " phone: ", v
        return phone_list

def importVCardFile( file, outfile ):
    global g_verbose
    # Read a VCARD-entry from file containing one or more entries
    # Each entry may have following format.
    # Starts with a 'BEGIN:VCARD', ends with 'END:VCARD'
    # We're just extracting the fields 'FN' and 'TEL'
    # - We'll add a name and a number for each TEL-subfield i.e. 'WORK', 'HOME', 'CELL' 
    #   name + 'WORK' = number
    #   name + 'CELL' = number
    #
    # BEGIN:VCARD
    # VERSION:2.1
    # N;CHARSET=UTF-8:SjÃ¶berg;Elisabet Eir
    # FN;CHARSET=UTF-8:Elisabet Eir SjÃ¶berg
    # TEL;WORK;VOICE:0812341234
    # TEL;CELL;VOICE:+46707774488
    # EMAIL;PREF;INTERNET:elisa...@somewhere.se
    # END:VCARD

    contacts = []

    cur_contact = VCardContact()
    for line in file:
        if line[0:11] == 'BEGIN:VCARD':
            # Start with a new fresh entry
            cur_contact.reset()
        elif line[0:9] == 'END:VCARD':
            # unpack a list of name+type = number into dictionary entry...
            cur_list = cur_contact.to_list() 
            for i in cur_list:
                # Phone dictionary entry only consists of 'tel' and 'name' fields
                entry = {}
                entry['tel'] = i[1]
                entry['name'] = i[0]
                if g_verbose:
                    print "Adding entry > ", entry
                contacts.append( entry )
        elif line[0:2] == 'FN':
            # Assign the the value of FN...
            cur_contact.setName( line[line.index(':')+1:] )
        elif line[0:3] == 'TEL':
            try:
                # phone_info will contain a list like
                # ['CELL', 'VOICE:+460812341234']
                phone_info = line[4:].split(';')
                # phone_number (just eat away the 'VOICE:')
                phone_number = phone_info[1].split(':')[1]

                cur_contact.addPhoneNumber( phone_info[0], phone_number )
            except:
                # if it's isn't in the format accepted above it probably isn't 
                # anything we want to add
                # I'm ignoring 'TEL;FAX...' for example...
                print "Exception parsing line: ", line

    if g_verbose:
        print "Contacts: ", contacts
    ofile = open( outfile, 'w' )
    pickle.dump( contacts, ofile, pickle.HIGHEST_PROTOCOL )

    print len(contacts), "Contacts were successfully written to file: ", outfile

def usage():
    print "VCard-file importer for Paroli contacts"
    print "Usage:"
    print " vcard_import.py {[-i|--infile] infile.vcf} [[-o|--outfile] phone] [-v|--verbose] [-h|--help]"
    print ""
    print " outfile : defaults to 'phone'"
    print ""
    print " To install the file on the phone, quit all (kill!) the Paroli applications." 
    print " Then copy the 'outfile' to the phone like:"
    print "$ scp 'outfile' r...@192.168.0.202:/home/root/.paroli/contacts/phone"
    print "     ('outfile' is the filename you specified for outfile-argument)"

def main():
    global g_verbose
    try:
        opts, args = getopt.getopt( sys.argv[1:], 'i:o:hv', ['infile=','outfile=','help','verbose'] )
    except getopt.GetoptError, err:
        print str(err)
        usage()
        sys.exit(2)

    if len(opts) < 1:
        usage()
        sys.exit(2)

    infile = "-"
    outfile = "phone"
    for o, a in opts:
        if o in ("-v", "--verbose"):
            g_verbose = True
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-i", "--infile"):
            infile = a
        elif o in ("-o", "--outfile"):
            outfile = a
        else:
            assert False, "unhandled option"
    # ...

    if infile == "-":
        print "Error: required argument '[-i | --infile] <filename>' is missing"
        usage()
        sys.exit(2)

    file = None
    try:
        file = open(infile, 'r')
    except:
        print "Error opening file: ", infile
        sys.exit(1)

    importVCardFile( file, outfile )

if __name__ == '__main__':
    main()

