#------------------------------------------------------------------------------
#   $Date: 2005/05/20 17:45:21 $
#   RCS: $Id: bbdbRecord.pm,v 1.3 2005/05/20 17:45:21 aaronkaplan Exp $
#------------------------------------------------------------------------------

package bbdbRecord;

use strict;

use bbdb::bbdb;
use bbdb::bbdbAddr;
use bbdb::bbdbPhone;

sub new {
    my $type = shift;
    my $self = {};
    my $str  = shift;
    my $ver  = shift || $bbdb::DEFAULT_VERSION;

    bless ($self, $type);
    
    if (not defined $str) {
      ## Empty record.
      $str = "[\"\" \"\" nil \"\" nil nil nil nil nil]";
    }
    $self->parse($str, $ver);
    $self;
}

sub toString
{
  my $self = shift;
  my $ret;

    if (defined $self->{'lname'}) {
	if (defined $self->{'fname'}) {
	    $ret = $self->{'lname'} . ", " . $self->{'fname'};
	} else {
	    $ret = $self->{'lname'};
	}
    } elsif  (defined $self->{'fname'}) {
	$ret = $self->{'fname'};
    } else {
      $ret = "???";
    }

  $ret .= " - " . $self->{org} if (defined $self->{org});
  $ret .= "\n";
  if (defined $self->{'email'} && scalar(@{$self->{'email'}})) {
    $ret .= join(", ", @{$self->{'email'}}) . "\n";
  }

  my $phone;
  foreach $phone (@{$self->{'phone'}}) {
    $ret .= $phone->toString(). "\n";
  }

  my $addr;
  foreach $addr (@{$self->{'addr'}}) {
    $ret .= $addr->toString() . "\n";
  }

  return $ret;
}

sub print
{
    my $self = shift;
    my $file = shift || \*STDOUT;

    print $file $self->toString() . "\n";

}

sub eStrObjLst
{
    my $lst = shift;
    my $ver  = shift || $bbdb::DEFAULT_VERSION;
    
    if (!$lst || !scalar(@{$lst})) {
	return "nil";
    }

    my $ret = "(";
    my $first = 1;
    my $item;
    foreach $item (@${lst}) {
	$ret .= " " if (!$first);
	$first = 0;
	$ret .= $item->ePStr($ver);
    }
    return $ret . ")";
}

sub eStrLst
{
    my $lst = shift;

    if (!$lst || !scalar(@{$lst})) {
	return "nil";
    }

    my $ret = "(";

    my $item;
    my $first = 1;
    foreach $item (@{$lst}) {
      if ($first) { $first = 0;  }
      else        { $ret .= " "; }
      $ret .= bbdb::eStr($item);
    }
    return $ret . ")";
}

sub eStrHash
{
    my $hash = shift;
    if (!scalar(keys(%{$hash}))) {
	return "nil";
    }

    my $ret = "(";
    my $first = 1;
    my $key;
    foreach $key (sort(keys(%{$hash}))) {
	$ret .= " " if (!$first);
	my $str = bbdb::eStr($$hash{$key});

	$key = "nil" if ($key eq "");  # bad key...

	if ($str ne "nil")
	{ $ret .= ("(" . $key . " . " . $str . ")"); }
	else
	{ $ret .= ("(" . $key . ")"); }

	$first = 0;
    }
    $ret .= ")";
    return $ret;
}

sub ePStr
{
  my $self = shift;
  my $ver  = shift || $bbdb::DEFAULT_VERSION;
  my $ret = ("[" .
	     bbdb::nStr($self->{'fname'}) . " " .
	     bbdb::nStr($self->{'lname'}) . " " .
	     eStrLst($self->{'aka'}) . " ".
	     bbdb::nStr($self->{'org'}) . " " .
	     eStrObjLst($self->{'phone'}, $ver) . " " .
	     eStrObjLst($self->{'addr'}, $ver) . " " .
	     eStrLst($self->{'email'}) . " " .
	     eStrHash($self->{'notes'}) . " " .
	     "nil]");
  return $ret;
}

sub eprint
{
  my $self = shift;
  my $ver  = shift;
  my $file = shift || \*STDOUT;
      
  print $file $self->ePStr($ver);
}

sub add_addr
{
  my $self = shift;
  my $addr = shift;

  my $ad = $self->{'addrH'}{$addr->{'name'}};
  if (! $ad) {
    push(@{$self->{'addr'}}, $addr);
  } else {
    my $a;
    foreach $a (@{$self->{'addr'}}) {
      if ($a == $ad) {
	$a = $addr;
	last;
      }
    }
  }
  $self->{'addrH'}{$addr->{'name'}} = $addr;
}

sub del_addr
{
    my $self = shift;
    my $name = shift;
    my $ad = $self->{'addrH'}{$name};
    return if (! $ad);
    
    my @rest;
    foreach $a (@{$self->{'addr'}}) {
	next if ($a == $ad);
	push(@rest, $a);
    }
    $self->{'addr'} = \@rest;
    delete $self->{'addrH'}{$name};
}

sub add_phone
{
  my $self = shift;
  my $phone = shift;

  my $ph = $self->{'phoneH'}{$phone->{'title'}};
  if (! $ph) {
    push(@{$self->{'phone'}}, $phone);
  } else {
    my $e;
    foreach $e (@{$self->{'phone'}}) {
      if ($e == $ph) {
	$e = $phone;
	last;
      }
    }
  }
  $self->{'phoneH'}{$phone->{'title'}} = $phone;
}

sub del_phone
{
    my $self = shift;
    my $name = shift;
    my $ph = $self->{'phoneH'}{$name};
    return if (!$ph);
    
    my @rest;
    foreach my $p (@{$self->{'phone'}}) {
	next if ($p == $ph);
	push(@rest, $p);
    }
    $self->{'phone'} = \@rest;
    delete $self->{'phoneH'}{$name};
}


sub parse
{
    my $self = shift;
    my $str  = shift;
    my $ver  = shift || $bbdb::DEFAULT_VERSION;

    # print "Str: $str\n";

    ## Strip leading & trailing brackets...
    $str =~ s/^\s*\[(.*)\]\s*$/$1/;
    
    my ($fn, $ln, $aka, $org, $ph, $ad, $net, $no) = bbdb::get_fields($str);

    $self->{'fname'} = $fn;
    $self->{'lname'} = $ln;
    $self->{'org'}   = $org;

    ($self->{'phone'}, $self->{'phoneH'}) = parse_phone($ph, $ver);
    ($self->{'addr'},  $self->{'addrH'})  = parse_addr($ad, $ver);

    push(@{$self->{'aka'}},   bbdb::get_fields($aka));
    push(@{$self->{'email'}}, bbdb::get_fields($net));

    $self->{'notes'} = parse_note($no, $ver);
}

sub parse_phone
{
    my $rec  = shift;
    my $ver  = shift || $bbdb::DEFAULT_VERSION;

    my $ret  = ();
    my $retH = {};

    return ($ret, $retH) if ($rec eq "nil");

    $rec =~ s/^\s*\[(.*)\]\s*$/$1/;

    my @rawPhones = split(/\]\s*\[/, $rec);
    my $phone;
    foreach $phone (@rawPhones) {
	my $obj = new bbdbPhone($phone, $ver);
	push(@$ret, $obj);
	$retH->{$obj->{'title'}} = $obj;
    }

    return ($ret, $retH);
}

sub parse_addr
{
    my $addrs = shift;
    my $ver   = shift || $bbdb::DEFAULT_VERSION;

    my $ret    = ();
    my $retH   = {};

    return $ret if ($addrs eq "nil");

    $addrs =~ s/^\s*\[(.*)\]\s*$/$1/;

    my @rawAddrs = split(/\]\s*\[/, $addrs);
    my $addr;
    foreach $addr (@rawAddrs) {
	my $obj = new bbdbAddr($addr, $ver);
	push(@{$ret}, $obj);
	$retH->{$obj->{'name'}} = $obj;
    }

    return ($ret, $retH);
}

sub parse_note
{
    my $rec = shift;
    my $ver = shift || $bbdb::DEFAULT_VERSION;

    my $ret = {};

    return $ret if ($rec eq "nil");

    my @rawNotes = bbdb::get_fields($rec);
    my $note;
    foreach $note (@rawNotes) {
      my ($tag, $value) = ($note =~ m/([^\s]*)\s*\.\s*\"((?:[^\\\"]|\\.)*)\"/);

      $value =~ s/\\n/\n/g;
      $value =~ s/\\(\d\d\d)/sprintf("%c",oct($1))/eg;
      $value =~ s/\\(.)/$1/g;
      $$ret{$tag} = $value;
    }

    return $ret;
}


1;
