package App::POS::DB;

use strict;
use warnings;
use Data::Dumper;
use File::Path qw( mkpath );
use Carp qw( confess );

my $DEBUG = 0;

sub new {
  my $c = shift;
  my %a = ( show_sql_errors => 1, dbh => undef, @_ );

  die "Missing 'dbh' parameter" unless defined $a{dbh};

  my $s = bless {%a}, ref($c) || $c;

  #
  # register my own functions
  #

  $s->register_functions();
  
  return $s;
}

sub register_functions {}

sub dbh { shift()->{dbh} }

sub copy_to {
  my $s = shift;
  my( $q, @p ) = @_;

  if ($DEBUG) {
    print STDERR ref($s).": copy_to - $q\n";
    print STDERR Dumper(\@p);
  }

  my $dbh = $s->dbh();

  # remove tabs, \n and \'s
  map { tr/\\\t\n/   /; } @p;

  $dbh->do($q);
  $dbh->pg_putline(join("\t", @p)."\n");
  $dbh->pg_endcopy();
}

sub select {
  my $s = shift;
  my( $q, @p ) = @_;

  if ($DEBUG) {
    print STDERR ref($s).": select - $q\n";
    print STDERR Dumper(\@p);
  }

  my $dbh = $s->dbh();
  my $sth;

  my $r = [];

  eval {
    $sth = $dbh->prepare($q);
    $sth->execute(@p);
  };

  if ($@) {
    if ($s->{show_sql_errors}) {
      print STDERR "ERROR... $@\nQUERY: $q, PARAMS: ".Dumper(\@p);
      #die("SQL ERROR");
      confess("SQL ERROR");
    }
  }

  my @fields = @{$sth->{NAME}};
  my %rec = ();

  $sth->bind_columns(map {\$rec{$_}} @fields);

  while ($sth->fetch) {
    push @$r, { %rec };
  }

  $sth->finish();

  return wantarray? @{$r || []} : $r;
}

sub select_iter_hash {
  my $s = shift;
  my( $q, @p ) = @_;

  my $dbh = $s->dbh();
  my $sth;

  eval {
    $sth = $dbh->prepare($q);
    $sth->execute(@p);
  };

  if ($@) {
    die $sth->errstr();
  }

  return sub {
    my $row;

    eval {
      $row = $sth->fetchrow_hashref();
    };

    if ($@) {
      return undef;
    } else {
      $sth->finish() unless $row;
      return $row;
    }
  }
}

sub select_iter {
  my $s = shift;
  my( $q, @p ) = @_;

  my $dbh = $s->dbh();
  my $sth;

  eval {
    $sth = $dbh->prepare($q);
    $sth->execute(@p);
  };

  if ($@) {
    die $sth->errstr();
  }

  return sub {
    my $row;
    eval {
      $row = $sth->fetchrow_arrayref();
    };
    if ($@) {
      return undef;
    } else {
      $sth->finish() unless $row;
      return $row;
    }
  }
}

sub last_id {
   my $s = shift;
   my( $table, $id_field ) = @_;
   my $dbh = $s->dbh();
   my $sth = $dbh->prepare("SELECT MAX(".$id_field.") FROM ".$table)
     or die $dbh->errstr();
   $sth->execute() or die $sth->errstr();
   my $arr = $sth->fetchall_arrayref();
   return $arr->[0]->[0];
}

sub do {
  my $s = shift;
  my( $q, @p ) = @_;

  if ($DEBUG) {
    print STDERR ref($s).": do - $q\n";
    print STDERR Dumper(\@p);
  }

  my $dbh = $s->dbh();
  my $sth;

  eval {
    $sth = $dbh->prepare($q) or $s->abort($dbh->errstr());
    $sth->execute(@p);
  };

  if ($@) {
    if ($s->{show_sql_errors}) {
      print STDERR "ERROR... $@\nQUERY: $q, PARAMS: ".Dumper(\@p);
      #die("SQL ERROR - $@");
      confess("SQL ERROR");
    }
  } else {
    return $sth->rows();
  }
}

1;

