#------------------------------------------------------------------------------
#   $Date: 2005/02/13 16:55:08 $
#   RCS: $Id: localHashDB.pm,v 1.2 2005/02/13 16:55:08 aaronkaplan Exp $
#------------------------------------------------------------------------------

package localHashDB;

use strict;
require  Digest::MD5;

require SyncUtil::localDB;
@localHashDB::ISA = qw(localDB);

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

  bless ($self, $type);

  $self->{'hashObj'}  = shift;
  $self->{'hash'} = {};
  $self->{'new-recs'} = [];
  $self->{'mismatch'} = {};

  return $self;
}

sub getRecords {
  my $self = shift;

  die "Subclass must implement getRecords to return all local records.";
}

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

  die ("Subclass must implement toString to return a string containing\n" .
       "all the pertinate information of record.\n"); 
}

sub hashRecord {
  my $self   = shift;
  my $rec = shift;
  my($hash) = new Digest::MD5;
  $hash->add($self->toString($rec));
  return $hash->hexdigest;
}

sub setup {
    my $self = shift;

    $self->localDB::setup(shift, shift);

    foreach my $rec (@{$self->getRecords()}) {

	$self->update(); # Give our host some time...

	my @ids = @{$self->getPilotIDs($rec)};
	
	if (!scalar(@ids)) {
	    push(@{$self->{'new-recs'}}, $rec);
	} else {
	    foreach my $id (@ids) {
		$self->{'hash'}{$id} = $rec;
	    }
	}
    }
}

sub getRec {
  my $self = shift;
  my $id   = shift;
  return $self->{'hash'}{$id};
}

sub addRec {
  my $self = shift;
  my $rec  = shift;
  my $hash = $self->hashRecord($rec);

  foreach my $id (@{$self->getPilotIDs($rec)}) {
      $self->{'hash'}{$id} = $rec;
      $self->{'hashObj'}->setLocalHash($id, $hash);
  }
}

sub deleteRec {
  my $self = shift;
  my $id   = shift;
  
  my $rec  = $self->{'hash'}{$id};
  return if (not defined $rec);

  foreach my $r (@{$self->getRecords()}) {
    if (defined $r) {
      $r = undef if ($r == $rec);
    }
  }

  $self->{'hashObj'}->setLocalHash($id, undef);
  $self->{'hashObj'}->setPilotHash($id, undef);

  return $rec;
}

sub lastSyncDate {
  my $self = shift;
  return $self->{'hashObj'}->syncDate();
}

sub getNew {
  my $self     = shift;

  return $self->{'new-recs'};
}

sub getMod {
  my $self     = shift;

  my @mod = ();

  foreach my $rec (@{$self->getRecords()}) {

    $self->update(); # Give our host some time...

    my @ids = @{$self->getPilotIDs($rec)};
    next if (! scalar(@ids));  ## new record not mod...

    my $old_hash = $self->{'hashObj'}->getLocalHash($ids[0]);

    my $new_hash = $self->hashRecord($rec);

    if (!defined $old_hash)
    {
	# We have a pilot id but our hash isn't in the ids file.
	# Something bad probably happened to our ids list...
	# we will assume this record was modified.
	$self->{'mismatch'}{$ids[0]} = $rec;
	$old_hash = "";  #force it not to match
    }

    if ($new_hash ne $old_hash)
    { 
	push(@mod,$rec); 
	foreach my $id (@ids) {
	    $self->{'hashObj'}->setLocalHash($id, $new_hash);
	}
    }
  }

  my @keys = keys(%{$self->{'mismatch'}});
  if (scalar @keys) 
  {
      my $x = scalar @keys;
      $self->getHost()->output
	  ("Found $x record(s) in BBDB with pilot-id's but not in ids file\n" .
	   "This probably indicates a problem with 'ids' file (deleted?).\n" .
	   "Examples: \n");

      $x=0;
      foreach my $k (@keys) {
	  $self->output($self->{'mismatch'}{$k});
	  last if (++$x == 10);
      }

      if ($x < scalar(@keys)) {
	  $self->getHost()->output("more...");
      }
  }

  return \@mod;
}

sub getDel {
  my $self     = shift;

  my @del = ();
  my $hashObj = $self->{'hashObj'};

  foreach my $id (keys %{$hashObj->{'ids'}}) {

    $self->update(); # Give our host some time...

    ## We have a local hash value for this ID but no record...
    ## must have been deleted...
    if ((!defined $self->{'hash'}{$id}) &&
	(defined $self->{'hashObj'}->getLocalHash($id))) {
      push(@del,$id) ;

      #Remove $id from the hash since it is going away...
      $hashObj->setLocalHash($id,undef);
    }
  }
  return \@del;
}

1;
