#------------------------------------------------------------------------------
#   $Date: 2006/05/01 19:40:48 $
#   RCS: $Id: pilotBBDB.pm,v 1.4 2006/05/01 19:40:48 aaronkaplan Exp $
#------------------------------------------------------------------------------

package pilotBBDB;

use strict;
require SyncUtil::pilotHashDB;
@pilotBBDB::ISA = qw(pilotHashDB);

sub new {
    my $type = shift;
    my $self = pilotHashDB->new(shift, shift, shift, shift);

    bless ($self, $type);

    $self->{'translate'} = shift;

    my $db              = $self->{'dlp'}->open("AddressDB");
    $self->{'db'}       = $db;

    my $appInfo         = $db->getAppBlock();
    $self->{'appInfo'}  = $appInfo;

    $self->{'CategoryNames'} = $appInfo->{'categoryName'};
    my @CategoryNames        = @{$self->{'CategoryNames'}};
    my $i = 0;
    foreach my $cat (@CategoryNames) {
      $self->{'CategoryHash'}{$cat} = $i++;
    }

    $self->{'phoneLabels'} = $appInfo->{'phoneLabel'};
    my @phoneLabels        = @{$self->{'phoneLabels'}};
    $i=0;
    foreach my $label (@phoneLabels) {
      $self->{'phoneLabelsHash'}{$label} = $i++;
    }

    $self->{'labels'} = $appInfo->{'label'};
    my @labels        = @{$self->{'labels'}};
    $i=0;
    foreach my $label (@labels) {
      $self->{'labelsHash'}{$label} = $i++;
    }

    $self->{'Fields'} = [ 'Last', 'First', 'Company',
			  'Field1', 'Field2', 'Field3','Field4', 'Field5',
			  'Address', 'City', 'State', 'Zip', 'Country',
			  'Title',
			  'Custom1', 'Custom2', 'Custom3', 'Custom4',
			  'Note'
			  ];
    $i=0;
    foreach my $f (@{$self->{'Fields'}}) {
	## map of fields to indexes in entry...
	$self->{'FieldMap'}{$f} = $i++;
    }

    $self;
}

sub name {
  my $self = shift;
  return "Pilot Address Book";
}

sub syncRec {
  my $self = shift;
  my $lrec = shift;


  my $map = new pilotBBDBMap($lrec, $self->{'translate'});

  my %origIDS;
  foreach my $rec (@{$map->{'records'}}) {
      # break any existing references...
      $self->{'hashObj'}->setLocalHash($rec->{'id'}, undef);
      delete $self->{'localDB'}->{'hash'}{$rec->{'id'}};

      # remember we were associated with this id...
      $origIDS{$rec->{'id'}} = 1;
  }

  # Update the mapping..
  $map->updateMappingFromBBDB($self);

  # make sure all the pilot records we think exist actually do exist.
  # Even if this means we need to create them...
  foreach my $rec (@{$map->{'records'}}) {
      my $prec = $self->getRec($rec->{'id'});
      if (! defined $prec) {
	  $prec = $self->newRec();
	  $rec->{'id'} = $prec->{'id'};
      }
      # we continue to reference these ids..
      delete $origIDS{$rec->{'id'}};
  }

  # This is the list of ids we used to reference but don't anymore...
  foreach my $id (keys %origIDS) {
      $self->deleteRec($id);
      $self->{'localDB'}->deleteRec($id);
  }

  $lrec->{'notes'}{'pilot-id'} = $map->toString();
  my $lhash = $self->{'localDB'}->hashRecord($lrec);


  foreach my $rec (@{$map->{'records'}}) {
      # Restore the new references
      $self->{'hashObj'}->setLocalHash($rec->{'id'}, $lhash);
      $self->{'localDB'}->{'hash'}{$rec->{'id'}} = $lrec;
  }

  foreach my $rec (@{$map->{'records'}}) {
      my $prec = $self->getRec($rec->{'id'});
      
      ## Most categoryy setup code is in pilotBBDBMap.pm
      my $category = $rec->{'category'};

       ## fallback case..
      $category = "Unfiled" if (not $category);

      $prec->{'category'} = 0; # also 'Unfiled'
      if (defined $self->{'CategoryHash'}{$category}) {
	  $prec->{'category'} = $self->{'CategoryHash'}{$category};
      }

      # to set which phone is shown in the one line display...

      # Standard stuff
      $self->setField($prec, 'Last',    $lrec->{'lname'});
      $self->setField($prec, 'First',   $lrec->{'fname'});
      $self->setField($prec, 'Company', $lrec->{'org'});

      $self->setField($prec, 'Title',   
		      $lrec->{'notes'}{'title'} || "");

      $self->setField($prec, 'Note',
		      $lrec->{'notes'}{'notes'} || "");

      if (defined $rec->{'name'} && 
	  defined $lrec->{'addrH'}{$rec->{'name'}}) {
	  my $addr = $lrec->{'addrH'}{$rec->{'name'}};
	  
	  $self->setField($prec, 'Address', 
			  join("\xA", @{$addr->{'street'}}));
	  $self->setField($prec, 'City',  $addr->{'city'});
	  $self->setField($prec, 'State', $addr->{'state'});
	  if (defined $addr->{'zip'}) {
	      $self->setField($prec, 'Zip', join(' ',@{$addr->{'zip'}}));
	  } else {
	      $self->setField($prec, 'Zip', "");
	  }
	  $self->setField($prec, 'Country', $addr->{'country'});
      } else {
	  $self->setField($prec, 'Address', "");
	  $self->setField($prec, 'City',    "");
	  $self->setField($prec, 'State',   "");
	  $self->setField($prec, 'Zip',     "");
	  $self->setField($prec, 'Country', "");
      }

      # Empty everything out...
      $self->setField($prec, 'Field1', "");
      $self->setField($prec, 'Field2', "");
      $self->setField($prec, 'Field3', "");
      $self->setField($prec, 'Field4', "");
      $self->setField($prec, 'Field5', "");
      $prec->{'phoneLabel'}[0] = 0;
      $prec->{'phoneLabel'}[1] = 1;
      $prec->{'phoneLabel'}[2] = 2;
      $prec->{'phoneLabel'}[3] = 3;
      $prec->{'phoneLabel'}[4] = 4;

      $self->setField($prec, 'Custom1', "");
      $self->setField($prec, 'Custom2', "");
      $self->setField($prec, 'Custom3', "");
      $self->setField($prec, 'Custom4', "");

      my $first=1;
      foreach my $ent (@{$rec->{'mappings'}}) {
	  my $btype = $ent->{'bbdb-type'};
	  my $bname = $ent->{'bbdb-name'};
	  my $val = "";
	  if ($btype eq "phone") {
	      $val = $lrec->{'phoneH'}{$bname}->phoneString();
	  } elsif ($btype eq "note") {
	      if ($bname ne 'notes') {
	          $val = $lrec->{'notes'}{$bname};
	      }
	      # $lrec->{'notes'}{'notes'} was already handled above.
	  } elsif ($btype eq "net") {
	      my @email = @{$lrec->{'email'}};
	      #$val = join("\xA",@email);
	      $val = $email[0];
	  } elsif ($btype eq "aka") {
	      my @aka = @{$lrec->{'aka'}};
	      $val = join(", ",@aka);
	  } else {
	      print "Unknown bbdb-type\n";
	  }
	  
	  # Set the fields value...
	  $self->setField($prec, $ent->{'pilot'}, $val);

	  if (defined $ent->{'pilot-label'}) {
	      if ($ent->{'pilot'} =~ m/Field(.)/) {
		  my $idx = $1; $idx--;
		  # Set the label for the field....
		  $prec->{'phoneLabel'}[$idx] = $ent->{'pilot-label'};
		  if ($first) {
		    # Set the one-line phone to the first entry...
		    # This really needs better support so I can
		    # remember if it was changed on the pilot...
		    $prec->{'showPhone'} = $idx;
		    $first = 0;
		  }

	      }
	  }
      }

      # Send the modified record back to the Pilot...
      $self->setRec($prec); # Also updates Hash
  }
}

sub printRec {
    my $self = shift;
    my $prec  = shift;

    my @fields = ('Last', 'First', 'Title', 'Company', 
		  'Address', 'City', 'State', 'Zip', 'Country',
		  'Field1', 'Field2', 'Field3', 'Field4', 'Field5',
		  'Custom1', 'Custom2', 'Custom3', 'Custom4',
		  'Note');
    foreach my $f (@fields) {
	print $f. ": " . $self->getField($prec, $f) . "\n";
    }
    print "Lables: " . join(", ", @{$prec->{'phoneLabel'}}) . "\n";
}


sub newRec {
    my $self = shift;

    my $ret = PDA::Pilot::AddressDatabase->record;

    $ret->{'id'} = 0;
    $ret->{'category'} = 0;
    $ret->{'entry'} = ["", "", "", "", "", "", 
		       "", "", "", "", "", "", 
		       "", "", "", "", "", ""];

    $ret->{'phoneLabel'} = [0 .. 4];
    $ret->{'secret'} = 0;
    
    $self->setRec($ret);
    return $ret;
}


sub dupRec {
  my $self = shift;
  my $prec = shift;
  my $lrec = shift;
  my $lcpy = shift;

  my $ret = PDA::Pilot::AddressDatabase->record;

  $ret->{'id'} = 0;  ## disassociate from original record...

  $ret->{'category'} = $prec->{'category'};
  
  my @dup = ();
  push(@dup, @{$prec->{'entry'}});
  $ret->{'entry'} = [@dup];

  @dup = ();
  push(@dup, @{$prec->{'phoneLabel'}});
  $ret->{'phoneLabel'} = [@dup];

  $ret->{'secret'}     = $prec->{'secret'};

  $self->setRec($ret);  # Get a record ID...

  my $map    = new pilotBBDBMap($lrec, $self->{'translate'});
  my $mapRec = $map->getMapForID($prec->{'id'});

  # setup new mapping for local rec.
  $map = new pilotBBDBMap($lcpy, $self->{'translate'});
  push(@{$map->{'records'}}, $mapRec->copy($ret->{'id'}));
  $lcpy->{'notes'}{'pilot-id'} = $map->toString();

  return $ret;
}

sub categoryStr {
  my $self = shift;
  my $rec  = shift;
  return ${$self->{'CategoryNames'}}[$rec->{'category'}];
}

sub getPhoneLabel {
  my $self = shift;
  my $indx = shift;
  return $self->{'phoneLabels'}[$indx];
}

sub getCustLabel {
  my $self = shift;
  my $indx = shift;
  return $self->{'labels'}[$indx+$self->getFieldIndex('Custom1')];
}

sub getFieldIndex {
  my $self  = shift;
  my $field = shift;
  return $self->{'FieldMap'}{$field};
}

sub getField {
  my $self  = shift;
  my $rec   = shift;
  my $field = shift;
  my $i     = $self->getFieldIndex($field);

  if (!defined $i) {
      print "Unkown Pilot field: $field\n" ;

      my $x=0;
      my ($pack, $file, $line, $subname);
      while (($pack, $file, $line, $subname) = caller($x++)) {
	  print "\tfile:$file line:$line\n";
      }
  }

  return $rec->{'entry'}[$i];
}

sub setField {
  my $self  = shift;
  my $rec   = shift;
  my $field = shift;
  my $val   = shift;

  my $indx = $self->getFieldIndex($field);
  print "Field: $field\n" if (not defined $indx) ;
  $rec->{'entry'}[$indx] = $val;
}

sub output {
  my $self = shift;
  my $rec  = shift;
  my $fn   = $self->getField($rec, 'First');
  my $ln   = $self->getField($rec, 'Last');
  my $org  = $self->getField($rec, 'Company');
  my $str  = "";
  
  $fn  = "" if !defined($fn);
  $ln  = "" if !defined($ln);
  $org = "" if !defined($org);

  $str = $fn;
  $str .= " "  if ($str && $ln);
  $str .= $ln;
  $str .= ", " if ($str && $org);
  $str .= $org;
  $str ||= "<No Name> - " . $rec->{'id'};
    
  $self->{'host'}->output($str . "\n");
}
1;
