#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# jp_lookup -- lookup records in the jppy address book
#
# Copyright © martin f. krafft <madduck@madduck.net>
# Released under the terms of the Artistic Licence 2.0
#
# $Id$
#

DEFAULT_OUTPUT_FIELDS='name,email,phone'
DEFAULT_WITH_LABELS=False
DEFAULT_VCARD=False

import sys, os
ME=os.path.basename(sys.argv[0])

if ME == 'jp_phone_lookup':
  DEFAULT_OUTPUT_FIELDS='name,company,phones'
  DEFAULT_WITH_LABELS=True
if ME == 'jp_mobile_lookup':
  DEFAULT_OUTPUT_FIELDS='name,mobile'
elif ME == 'jp_email_lookup':
  DEFAULT_OUTPUT_FIELDS='name,company,emails'
elif ME == 'jp_address_lookup':
  DEFAULT_OUTPUT_FIELDS='name,company,address'
elif ME == 'jp_vcard_lookup':
  DEFAULT_VCARD=True

SINGLE_LINE_FIELD_DELIMITER=';'
SINGLE_LINE_LABEL_DELIMITER=':'

from optparse import OptionParser
parser = OptionParser()
parser.add_option('-o', '--output-fields', dest='output_fields',
                  help='comma-separated list of fields to output',
                  metavar='FIELD_LIST', default=DEFAULT_OUTPUT_FIELDS)
parser.add_option('-1', '--only-first', dest='only_first',
                  help='only ever print the first matching record',
                  default=False, action="store_true")
parser.add_option('-s', '--single-line', dest='single_line',
                  help='output each record on a single line',
                  default=False, action="store_true")
parser.add_option('-l', '--with-labels', dest='with_labels',
                  help='include labels in output',
                  default=DEFAULT_WITH_LABELS, action="store_true")
parser.add_option('-c', '--vcard', dest='vcard',
                  help='select vcard as output format',
                  default=DEFAULT_VCARD, action="store_true")
parser.add_option('--first-name-last', dest='first_name_last',
                  help='print the first name after the last name',
                  default=False, action="store_true")
parser.add_option('--with-country', dest='with_country',
                  help='include country with address output',
                  default=False, action="store_true")
parser.add_option('--field-delimiter', dest='field_delimiter',
                  help='delimiter to use between fields in single-line output mode',
                  metavar='DELIMITER', default=SINGLE_LINE_FIELD_DELIMITER)
parser.add_option('--label-delimiter', dest='label_delimiter',
                  help='delimiter to use between label and value in single-line output mode',
                  metavar='DELIMITER', default=SINGLE_LINE_LABEL_DELIMITER)
#parser.add_option('-s', '--search-fields', dest='search_fields',
#                  help='comma-delimited list of fields to search, or all',
#                  default='all')

parser.usage = '%s [search term [search term [...] ] ]' % ME
options, args = parser.parse_args()

output_fields = options.output_fields.split(',')

if options.single_line:
  record_delim = '\n'
  field_delim = options.field_delimiter
  label_delim = options.label_delimiter
  address_delim = ' / '
else:
  record_delim = '\n*****\n'
  field_delim = '\n'
  label_delim = ': '
  address_delim = '\n'

FIELD_LABELS = \
    { 'firstname' : 'First name'
    , 'lastname' : 'Last name'
    , 'emails' : 'Email'
    , 'currentphone' : 'Primary phone'
    # 'anything' : 'Anything' -- done automatically
    }

COUNTRIES_ENGLISH = \
    { 'at' : 'Austria'
    , 'ca' : 'Canada'
    , 'ch' : 'Switzerland'
    , 'de' : 'Germany'
    , 'dk' : 'Denmark'
    , 'fi' : 'Finland'
    , 'fr' : 'France'
    , 'it' : 'Italy'
    , 'nl' : 'Netherlands'
    , 'no' : 'Norway'
    , 'se' : 'Sweden'
    , 'uk' : 'United Kingdom'
    , 'us' : 'USA'
    , 'ie' : 'Ireland'
    }

COUNTRY_ADDRESS_TEMPLATES = \
    { 'DEFAULT' : '%(street)s%(address_delim)s%(zip)s %(city)s'
    , 'us' : '%(street)s%(address_delim)s%(city)s, %(state)s %(zip)s'
    , 'ie' : '%(street)s%(address_delim)s%(city)s'
    }

def get_name(r):
  if options.first_name_last:
    name = ('%s, %s' % (r['lastname'], r['firstname'])).strip(' ,')
  else:
    name = ('%s %s' % (r['firstname'], r['lastname'])).strip()

  company = r['company']
  if not name and 'company' not in output_fields and len(company) > 0:
    name = company
  
  return name

def get_address(r):
  index = 1
  country = r['country%d' % index]
  template = COUNTRY_ADDRESS_TEMPLATES.get(country,
      COUNTRY_ADDRESS_TEMPLATES['DEFAULT'])
  data = { 'street' : r['address%d' % index]
         , 'zip' : r['zip%d' % index]
         , 'city' : r['city%d' % index]
         , 'state' : r['state%d' % index]
         , 'address_delim' : address_delim
         }
  value = template % data

  if options.with_country:
    country = COUNTRIES_ENGLISH.get(country, "'%s'" % country)
    value += '%s%s' % (address_delim, country)

  return value.strip(' ,\n')

def get_emails(r):
  value = []
  for entry in r['phones_with_labels']:
    if entry[1] != 4: continue
    if len(entry[0]) > 0:
      value.append(entry[0])
  return value

PHONE_LABELS = { 0 : 'work'
               , 1 : 'home'
               , 2 : 'fax'
               , 3 : 'other'
               # 4 : 'email' purposely left out.
               , 5 : 'main'
               , 6 : 'pager'
               , 7 : 'mobile'
               }

def get_phones(r):
  value = []
  for entry in r['phones_with_labels']:
    label = PHONE_LABELS.get(entry[1], None)
    if label is None: continue
    if len(entry[0]) > 0:
      value.append((label, entry[0]))
  return value

FIELD_MAPS = { 'name' : get_name
             , 'address' : get_address
             , 'phone' : 'currentphone'
             , 'emails' : get_emails
             , 'phones' : get_phones
             }

from jppy import addressBook as ab

records = ab().records(search=' '.join(args))

output_all = ''
first_record = True
for r in records:
  if options.vcard:
    vcard = list(r.vcard().split('\r\n'))
    name = None
    org = None
    for field in vcard:
      if field.startswith('N:'): name = field
      if field.startswith('ORG:'): org = field

    if name is None and org is not None:
      vcard.insert(3,'N:%s' % org[4:])

    output_all += '\r\n'.join(vcard)
    continue

  if not first_record and options.only_first: break

  output = ''
  first_field = True
  for f in output_fields:

    try:
      proxy = FIELD_MAPS.get(f, f)
      if callable(proxy): values = proxy(r)
      else: values = r[proxy]
    except KeyError:
      sys.stderr.write('no such field: %s, skipping...' % f)
      continue

    if not isinstance(values, (tuple, list)):
      values = (values,)

    def get_label(f):
      return FIELD_LABELS.get(f, f.capitalize())

    for i in values:
      if isinstance(i, (tuple, list)):
        f = i[0]
        value = i[1]
      else:
        value = i

      if not value: continue

      if options.with_labels:
        if options.single_line:
          label = '%s%s' % (f, label_delim)
        else:
          label = '%s%s' % (get_label(f), label_delim)
      else:
        label = ''

      if not first_field:
        output += field_delim
      first_field = False

      output += '%s%s' % (label, value)

  first_record = False
  output = output.strip(' ,\n')
  if not output: continue
  output_all += output + record_delim

if len(records) > 0:
  sys.stdout.write('%s\n' % output_all.rstrip('*\n '))
