#!/usr/bin/perl

use strict;
use CGI;

#use Opals::Constant;
use Opals::Context;

#use SIP::Map;
use SIP::Template;
use SIP::Session;

use SIP::Utility;

my $dbh = Opals::Context->dbh();
END { $dbh->disconnect(); }

my $cgi = CGI->new;

# $cgi->param('aaa') returns an array of aaa
my $input = $cgi->Vars();

#my $op = $input->{'op'};
my $util = SIP::Utility->new();

my $template = SIP::Template->new(filename => 'hold.tmpl',);

my ($ok, $available) = ('false', 'false');

my $transaction_datetime = $util->now();
my @dt = split(/ /, $transaction_datetime);
my $transaction_date =~ $dt[0];

my $dExpiry = $input->{'expiration_date'};

my $barcode = $input->{'item_identifier'};
my $title   = $input->{'title_identifier'};

my $session = SIP::Session->new(
  dbh               => $dbh,
  session_id        => $input->{'session_id'},
  patron_identifier => $input->{'patron_identifier'},
  item_identifier   => $barcode,
  title_identifier  => $title
);
$session->validate(
  patron_identifier => 1,
  account_expiry    => 1,
  item_identifier   => (defined $barcode),
  title_identifier  => (defined $title)
);

my $screen_message = $session->get('screen_message');
my $user           = $session->get('user');
my $record         = $session->get('record');

my ($queue_position, $pickup_location) = ('', '');

if ($session->isValid()) {
  my $hold_mode = $input->{'hold_mode'};
  my $reserveID = circ_getReserveID($dbh, $record->{'rid'}, $user->{'uid'});
  my $dTransaction = $util->format_datetime($transaction_datetime);

  ########################################
  # add
  if ($hold_mode eq '+' && isReservable($reserveID, $user->{'uid'}) == 'true') {
    my $recInfo = circ_getRecInfo($dbh, $record->{'rid'}, $user->{'uid'});
    my $numCopyReserve = 1;    # SIP does not specify multiple reserves

    if ($dExpiry) {
      $dExpiry = $util->format_datetime($dExpiry);
    }
    else {
      $dExpiry = date_getDeadLineDate($recInfo->{'reservePeriod'},
        $transaction_date);
    }

    my $reserveID = circ_placeReserve($dbh, $user->{'uid'}, $record->{'rid'},
      $numCopyReserve, $dTransaction, $dExpiry);

    if ($reserveID) {
      $ok = 'true';

      # put item on hold
      if (circ_numItemsAvailable($dbh, $record->{'rid'})) {
        $dExpiry = date_getDeadLineDate($recInfo->{'holdPeriod'},
          $transaction_date);

        if (circ_fillReserve($dbh, $user->{'uid'}, $record->{'rid'}) &&
          circ_placeHold($dbh, $reserveID, $dTransaction, $dExpiry)) {
          $available = 'true';
        }
      }
    }
  }
  ########################################
  # delete
  elsif ($hold_mode eq '-' && $reserveID) {
    circ_cancelHoldReserve($dbh, $idReserve, $dTransaction);
    $ok ='true';

    if (circ_numItemsAvailable($dbh, $record->{'rid'})) {
      $available = 'true';
    }
  }
  ########################################
  # change
  # OPALS does not support changes to reserve/hold
  elsif ($hold_mode eq '*' && $reserveID) {
  }
}

my $response = {
  debug             => $session->get('debug'),
  ok                => $ok,
  available         => $available,
  transaction_date  => $util->format_datetime($transaction_datetime, 'SIP'),
  expiration_date   => $util->format_datetime($dExpiry, 'SIP'),
  queue_position    => $queue_position,
  pickup_location   => $pickup_location, # not available in OPALS
  institution_id    => $input->{'institution_id'},
  patron_identifier => $input->{'patron_identifier'},
  item_identifier   => $barcode,
  title_identifier  => $title,
  screen_message    => $screen_message,
};

$template->param($response);

$template->write(cgi => $cgi);
################################################################################

sub isReservable {
  my ($reserveID, $uid) = @_;

  # check if already reserved using reserve ID
  if ($reserveID) {
    return 'false';
  }

  my ($sql, @values);

  # get reserves limit
  $sql = <<_SQL_;
select  c.maxreserv 
from    opl_user u inner join opl_category c on u.categorycode = c.catid
where   u.uid = ?
_SQL_
  @values = ($uid);
  my ($maxreserv) = $dbh->selectrow_array($sql, undef, @values);
  ($maxreserv) || ($maxreserv = 0);

  return 'false' unless $maxreserv;

  # count number of copies reserved
  $sql = <<_SQL_;
select  sum(numCopyReserve) nReserve
from    opl_reserve
where   numCopyReserve >= 1
     && dateExpiry > now()
     && dateCancel is null 
     && uid = ?
group by uid
_SQL_
  @values = ($uid);
  my ($nReserve) = $dbh->selectrow_array($sql, undef, @values);
  ($nReserve) || ($nReserve = 0);

  #count number of copies on hold
  $sql = <<_SQL_;
select  count(*)
from    opl_hold h inner join opl_reserve r using (idReserve)
where   uid = ?
     && idloan = 0
     && h.dateExpiry > now()
     && h.dateCancel is null
_SQL_
  @values = ($uid);
  my ($nHold) = $dbh->selectrow_array($sql, undef, @values);
  ($nHold) || ($nHold = 0);

  # check if reservable using reserve/hold counts
  return ($maxreserv > ($nReserve + $nHold)) ? 'true' : 'false';
}
############################################################
