###################################################################

package KoLBot::DBStateManager;
 
# Copyright (c) 2004 Alan W. Mahoney. All rights reserved. 
# This program is free software.  You may modify and/or 
# distribute it under the same terms as Perl itself.  
# This copyright notice must remain attached to the file.  
#
# Forms a base class for an Database Managed state manager.

use warnings;
use strict;

use Carp;
use Storable qw( lock_store lock_retrieve );

use Fcntl qw( :DEFAULT :flock);

use DBI;

use KoLBot::StateManager;

BEGIN 
{
  use Exporter ();
  our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $ID);

  $VERSION     = 0.5;
  $ID          = '$Id';

  @ISA         = qw(Exporter KoLBot::StateManager);
  @EXPORT      = qw();
  %EXPORT_TAGS = ( );

  @EXPORT_OK   = qw();
}

our @EXPORT_OK;

##########################################
## element access
##########################################

for my $field (qw( 
		   dbh
		   table_name
		   )) {
  no strict "refs";
  *$field = sub {
    my $self = shift;
    $self->{$field} = shift if @_;
    return $self->{$field};
  }
}

##########################################
## Constructor:
##########################################

sub new {
  my $invocant = shift;
  my $class = ref($invocant) || $invocant;
  my $sm = { 
		  @_ };
  bless $sm, $class;
}

##########################################
## The rest
##########################################

sub set {
  my $sm = shift;
  my $id = shift;
  my $class = shift;
  my $state = shift;

  croak "DBStateManager::set requires a (hash/class) ref, ",ref($state)
    unless ref($state);

  if($id =~ /.{32}/) {
    die "id $id is too long\n";
    return;
  }

  my $MANAGED_STATE_TABLE = $sm->table_name;

  for(values %{$state}) {
    if(ref($_)) {
      die "Reference pased to DBStateManager::set";
    }
  }

  my $sql = qq{
    DELETE FROM $MANAGED_STATE_TABLE WHERE id=? AND class = ?
    };
  $sm->{s_st_d} = $sm->{dbh}->prepare_cached($sql);

  my $rv = $sm->{s_st_d}->execute(lc($id),$class);
  undef($rv) and die "Setting state";

  $sql = qq{
    INSERT INTO $MANAGED_STATE_TABLE 
      (var_value,id,class,var_name) 
      VALUES (?,?,?,?)
    };
  $sm->{s_st_i} = $sm->dbh->prepare_cached($sql);
  
  my @status;
  $rv = $sm->{s_st_i}->execute_array({ArrayTupleStatus => \@status},
				     [values %$state],
				     lc($id),
				     $class,
				     [keys %$state],
				     );
  undef($rv) and die "Setting state";
}

sub get {
  my $sm = shift;
  my $id = shift;
  my $class = shift;

  my $MANAGED_STATE_TABLE = $sm->table_name;

#  unless ($sm->{g_st}){
  my $sql = qq{
    SELECT var_name,var_value FROM $MANAGED_STATE_TABLE
      WHERE id = ? AND class = ?
    };
  my $g_st = $sm->dbh->prepare_cached($sql);
#  }

  my $rv = $g_st->execute(lc($id),$class);
  
  $g_st->finish(),return {} if $rv < 1;

  my $state = {};
  while (my $row = $g_st->fetchrow_hashref) {
    $state->{$row->{var_name}} = $row->{var_value};
  }
  $g_st->finish();
#  print "AWM DEBUG, in DBSM, ",$state->{song},"\n";
  return $state;
}

# sub get {
#   my $sm = shift;
#   my $id = shift;
#   my $class = shift;

#   my $MANAGED_STATE_TABLE = $sm->table_name;

# #  unless ($sm->{g_st}){
#   my $sql = qq{
#     SELECT var_name,var_value FROM $MANAGED_STATE_TABLE
#       WHERE id = ? AND class = ?
#     };
#   $sm->{g_st} = $sm->dbh->prepare_cached($sql);
# #  }

#   my $rv = $sm->{g_st}->execute(lc($id),$class);
  
#   return {} if $rv < 1;

#   my $state = {};
#   while (my $row = $sm->{g_st}->fetchrow_hashref) {
#     $state->{$row->{var_name}} = $row->{var_value};
#   }
# #  print "AWM DEBUG, in DBSM, ",$state->{song},"\n";
#   return $state;
# }
  
END {} ;

1;

