#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
# $Id$
#------------------------------------------------------------
package Common::DB::ItemWithHistory;

use strict;
use warnings;
use Data::Dumper;
use lib '/app/tools/common/lib';
use Common::DB::AutoLock;
use Common::RSDB;
use Common::RSApp;
use Common::Assert;
use Common::Log;
use Common::DB::Item;
use base 'Common::DB::Item';

use Data::Dumper;

use constant kActionUpdate => 'updt';
use constant kActionDelete => 'delt';

# Virtual method that each class must override to return
# a new instance of it's particular archive DB::Item.
# Note that this method should NOT call 'save' on the object.
#
sub _NewArchiveItem {
    my ( $class, %args ) = @_;
    assert( 0, 'override' );
}

# Override this to return the name of the archive table for this class.
#
sub _ArchiveTableName {
    assert( 0, 'override' );
}

sub _archiveItem {
    my ( $self, $action, $tableName, $where, $values ) = @_;

    assert($action);

    # Need to strip out any extra stuff in @$values - If we were
    # doing an update then that will contain the data that is changing.
    # The keys are always last.
    #
    # seems unlikely that we'd have nothing in the where array at this stage, but
    # I don't want bizarre things to happen...
    #
    my %lookupArgs;
    my $whereSize  = scalar @$where;
    my $valuesSize = scalar @$values;
    assert( $whereSize > 0 && $valuesSize > 0 && $valuesSize >= $whereSize );

    my $indexDelta = $valuesSize - $whereSize;

    for ( my $i = $whereSize ; $i > 0 ; $i-- ) {
        my $key = $where->[ $i - 1 ];
        $key =~ s/=\?//;
        $lookupArgs{$key} = $values->[ $i + $indexDelta - 1 ];
    }

    my $class     = ref($self);
    my $oldRecord = $class->Lookup(%lookupArgs);

    # Now copy all the fields.
    #
    my %createHash;
    my $config = $self->_config();
    foreach my $fieldName ( keys %$config ) {
        next if ( '_' eq substr( $fieldName, 0, 1 ) );

        # Unlike the seldom-used 'Copy' static class method, I actually do want to copy
        # _all_ the fields, including autoincrement, onCreate, etc.

        $createHash{$fieldName} = $oldRecord->$fieldName();
    }

    # Now, finally, create the freaking copy!
    #
    my $archiveItem = $class->_NewArchiveItem(%createHash);
    $archiveItem->archive_action($action);
    $archiveItem->save();
}

sub _doDelete {
    my ( $self, $dbo, $tableName, $where, $values ) = @_;

    my $lock = Common::DB::AutoLock->new( $dbo, $tableName, $self->_ArchiveTableName );
    $self->_archiveItem( kActionDelete, $tableName, $where, $values );

    $self->SUPER::_doDelete( $dbo, $tableName, $where, $values );
}

sub _doUpdate {
    my ( $self, $dbo, $tableName, $set, $where, $values ) = @_;

    my $lock = Common::DB::AutoLock->new( $dbo, $tableName, $self->_ArchiveTableName );
    $self->_archiveItem( kActionUpdate, $tableName, $where, $values );

    $self->SUPER::_doUpdate( $dbo, $tableName, $set, $where, $values );
}

1;
