#!/usr/bin/perl

use strict;
use CGI;

use Opals::Context;
use Opals::Template qw(
    tmpl_read
    tmpl_write
    tmpl_preference

);

use POSIX qw(
    floor
);

use Opals::Date qw(
    date_time_text
    date_deltaWorkDay   
    date_parse

);

use Time::localtime;

use Opals::Constant;

use Opals::User qw(
    user_getInformationById
);

use Opals::Equipment qw(
    
    eq_def_colDisplayCount

);

use Opals::Eq_BarcodeMgmt qw(
    eq_bcm_validateBc
);

use Opals::Eq_Circulation qw(
    
    circ_getItemInfo
    circ_getItemStatus
    circ_processReturn
    circ_getUserListLoan
    circ_getUserListReserve

    circ_fillReserve

    circ_placeHold

    circ_processRenew

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

my $cgi = CGI->new;
my $input = $cgi->Vars();
my ($permission, $cookieList, $template) = tmpl_read(
    {
        dbh             => $dbh,
        cgi             => $cgi,
        tmplFile        => 'eqmnt/return.tmpl',
        reqPermission   => 'eq_circ_return',
    }
);
my $syspref    = tmpl_preference($dbh);
my $validateBc       = $syspref->{'validateBarcode'};
my $barcodeType      = $syspref->{'barcodeType'};

my $tm = localtime;
my $todayStr = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $tm->year+1900, ($tm->mon)+1, $tm->mday, $tm->hour, $tm->min, $tm->sec);

my $barcode = $input->{'bc'};
$barcode    =~ s/^\s+|\s+$//g;
$barcode = eq_bcm_validateBc($dbh, $barcode, $barcodeType) if ($validateBc eq '1');
my $uid = $input->{'uid'};
if ($barcode){
    my ($retRS,$return) = processReturn($dbh, $barcode);
    my $damaged_odl_id =0;
    if($input->{'condition'} =~ m/^damaged$/i){
        circ_updateItemStatus($dbh, $barcode, ITEM_DAMAGED);
        if ($retRS->{'idLoan'}){
             my $idloan = $retRS->{'idLoan'};
             $damaged_odl_id = circ_record_ODL($dbh,$idloan,'damaged',0);
        }
    }

    my $retStatusCode   = 'retStatusCode_' .$retRS->{'retStatusCode'};
    $template->param(
        rid                     => $retRS->{'rid'},
        rname                   => $retRS->{'rname'},
        barcode                 => $barcode,
        $retStatusCode          => 1,
        returnOne               => 1,
        reserveUserUid          => $retRS->{'reserveUserUid'},
        reserveUserFirstname    => $retRS->{'reserveUserFirstname'},
        reserveUserLastname     => $retRS->{'reserveUserLastname'},
        reserveUserBarcode      => $retRS->{'reserveUserBarcode'},
        holdUserFirstname       => $retRS->{'holdUserFirstname'},
        holdUserLastname        => $retRS->{'holdUserLastname'},
        holdUserBarcode         => $retRS->{'holdUserBarcode'},
    );
    getUserInfo($dbh, $retRS->{'uid'});
}
elsif ($input->{'op'} eq 'return'){
    my @arrReturn = split /,/,$input->{'itemList'};
    my @retHoldRsList;
    my $retRS ;
    my $return;
    for (my $i=0; $i<scalar(@arrReturn); $i++)
    {
        ($retRS, $return) = processReturn($dbh, @arrReturn[$i]);
         my $damaged_odl_id =0;
         if($input->{'condition'} =~ m/^damaged$/i){
            circ_updateItemStatus($dbh, $barcode, ITEM_DAMAGED);
            if ($retRS->{'idLoan'}){
                my $idloan = $retRS->{'idLoan'};
                $damaged_odl_id = circ_record_ODL($dbh,$idloan,'damaged',0);
            }
        }

        if ($retRS->{'retStatusCode'} eq '20' || $retRS->{'retStatusCode'} eq '21' || $retRS->{'retStatusCode'} eq '22' ){
            push @retHoldRsList, $retRS;
        }
    }
    getUserInfo($dbh, $uid);
    $template->param(retHoldRsList=>\@retHoldRsList);
}
elsif($input->{'op'} eq 'renew'){
    my $rndateDue = "";
    if ( 'seldate' eq $input->{'renewDate'}){
        my $numb        = $input->{'rndateDue'};
        my $hourOrDay   = $input->{'rnhourOrDay'};
        if ($numb && $hourOrDay && $numb > 0){
            $rndateDue = formatStrDateDue($numb, $hourOrDay);  
        }
    }

    my $renewError = processRenew($dbh, $uid, $input->{'itemList'}, $rndateDue);
    if (scalar(@$renewError)){
        if (@$renewError[2] == 0){
            $template->param(renewalMaxError=>1);}
        $template->param(renewalError=>1, renewFailList=>\@$renewError);
    }
    getUserInfo($dbh, $uid);
}

tmpl_write($dbh, $cgi, $cookieList, $template);

#--------------------------------------
sub processReturn{
    my ($dbh, $barcode ) = @_;
    my $itemCircStatus  = circ_getItemStatus($dbh, {barcode=>$barcode});
    my $itemInfo        = circ_getItemInfo($dbh, $barcode, undef);
    my $return;
    my $retVal ;

    #$retVal->{'itemInfo'}   =  $itemInfo;
    $retVal = {
        rid     =>  $itemInfo->{'rid'},
        rname   =>  $itemInfo->{'rname'},
    };
    my $overdue;

    if ($itemCircStatus->{'status'} == IT_STAT_ONLOAN 
            || $itemCircStatus->{'status'} == IT_STAT_HAVE_RSVR
            || $itemCircStatus->{'status'} == IT_STAT_HOLD_EXPIRE){
        if ($itemCircStatus->{'status'} == IT_STAT_ONLOAN 
            || $itemCircStatus->{'status'} == IT_STAT_HAVE_RSVR){
            $retVal->{'idLoan'} = $itemCircStatus->{'l_idLoan'};
            $return = doReturn($dbh, $itemCircStatus->{'l_uid'}, $barcode, $todayStr);
            $overdue    = $itemCircStatus->{'l_duedate'} < $todayStr ? 1:0;
            $retVal->{'uid'} = $itemCircStatus->{'l_uid'};

        }
        my $reserveList = $itemCircStatus->{'reserveList'};
        #check if item is on reserved
        if (!$reserveList || scalar(@$reserveList) == 0){
            $retVal->{'retStatusCode'} = "1$overdue";
        }
        else{
            if ($itemCircStatus->{'status'} == IT_STAT_HOLD_EXPIRE){
                $retVal->{'retStatusCode'} = "22";  }
            else {
                $retVal->{'retStatusCode'} = "2$overdue";   }
            my ($idReserve, $uidReserve, $reserveExpiry, $dateExpiry);
            $idReserve      = $reserveList->[0]->{'idReserve'};
            $uidReserve     = $reserveList->[0]->{'uid'};
            $reserveExpiry  = $reserveList->[0]->{'dateExpiry'};
            
            $itemInfo   = circ_getItemInfo($dbh, $barcode, $uidReserve);
            $dateExpiry = getDeadLineDate($itemInfo->{'holdPeriod'}, $todayStr);
            #if ($dateExpiry >  $reserveExpiry){
            #    $dateExpiry = $reserveExpiry;  }
            circ_fillReserve($dbh, $uidReserve, $itemCircStatus->{'rid'});
            circ_placeHold($dbh, $idReserve, $todayStr, $dateExpiry);
            my ($reserveUser, $guardien) = user_getInformationById($dbh, $uidReserve);
            $retVal->{'reserveUserUid'}         = $uidReserve;
            $retVal->{'reserveUserLastname'}    = $reserveUser->{'lastname'};
            $retVal->{'reserveUserFirstname'}   = $reserveUser->{'firstname'};
            $retVal->{'reserveUserBarcode'}     = $reserveUser->{'userbarcode'};
        }
    }
    elsif ($itemCircStatus->{'status'} == IT_STAT_LOST) {
        $retVal->{'retStatusCode'} = "30";
        circ_setAvailable($dbh, $barcode, IT_STAT_LOST);
    }
    elsif ($itemCircStatus->{'status'} == IT_STAT_NOEXIST){
        $retVal->{'retStatusCode'} = "40";
    }
    elsif ( $itemCircStatus->{'status'} == IT_STAT_ONHOLD){
        $retVal->{'retStatusCode'} = "50";
        my $holdList = $itemCircStatus->{'holdList'};
        $retVal->{'holdUserFirstname'} = $holdList->[0]->{'firstname'};
        $retVal->{'holdUserLastname'} = $holdList->[0]->{'lastname'};
        $retVal->{'holdUserBarcode'} = $holdList->[0]->{'userbarcode'};
    }
    elsif( $itemCircStatus->{'status'} == IT_STAT_MISSING){
        $retVal->{'retStatusCode'} = "70";
        if ($input->{'Condition'} eq "Damaged"){
            circ_updateItemStatus($dbh, $barcode, ITEM_DAMAGED);
        }
        else{
            circ_setAvailable($dbh, $barcode, IT_STAT_MISSING);
        }
    }
    else{
        $retVal->{'retStatusCode'} = "60";
    }
    return ($retVal,$return);
}

sub doReturn{
    my ($dbh, $uid, $barcode, $dateReturn) = @_;
    my $sth = $dbh->prepare("select id as idLoan, dateDue from eq_loan where uid=? && barcode =? && dateReturn is null");
    $sth->execute($uid,$barcode);
    my $rec = $sth->fetchrow_hashref;
    my ($idLoan,$dateDue) = ($rec->{'idLoan'}, date_parse($rec->{'dateDue'}));
    my $dateRet = date_parse($dateReturn);
    my $odCount = date_deltaWorkDay($dateDue,$dateRet) ;
    $odCount =0 if ($odCount <= 0);
    my $odl_id = 0;
    if ($odCount > 0) {
        $odl_id = circ_record_ODL($dbh,$idLoan,'overdue',$odCount);
    }
    $sth->finish;
    my $return = {lid=>$idLoan, overdue=>$odCount, odl_id=>$odl_id};
    circ_processReturn($dbh, {uid=>$uid, barcode=>$barcode, dateReturn=>$dateReturn});
    return $return;
}

sub processRenew{
    my ($dbh, $uid, $bcList, $inDueDate) = @_;    
    my @arrRenew = split /,/,$bcList;
    my @renewFailList = ();
    my $renewStatus;
    my $renewable;
    for (my $i = 0; $i < scalar(@arrRenew); $i++){
        my $itemCircStatus  = circ_getItemStatus($dbh, {barcode=>$arrRenew[$i]});
        my $itemInfo        = circ_getItemInfo($dbh, $arrRenew[$i], $uid);
        $renewStatus = 0;
        $renewable = ($itemCircStatus->{'renewalCount'} < $itemCircStatus->{'maxRenewal'})?1:0;
        if ($itemCircStatus->{'l_uid'} == $uid && $renewable){
            my $dateDue = ($inDueDate ne '')? $inDueDate : getDeadLineDate($itemInfo->{'renewalPeriod'}, $itemCircStatus->{'l_duedate'});
            $renewStatus = circ_processRenew($dbh, {uid=>$uid, barcode=>$arrRenew[$i],rnDate=>$dateDue});
        }
        if (! $renewStatus){
            push @renewFailList, {bc=>$arrRenew[$i], rname=>$itemInfo->{'rname'}};
        }
    }
    
    return \@renewFailList;
}

sub getUserInfo{
    my ($dbh, $uid) = @_;
    my ($userInfo, $guardian) = user_getInformationById($dbh, $uid);
    getLoanItemList($dbh, $template,$uid);
    getReservedItemList($dbh, $template, $uid);

    my $balance = 0;
    $balance = floor($balance*100  + 0.50)/100;
    $balance = sprintf("%.2f",$balance);

    $template->param(
        user_uid        => $userInfo->{'uid'},
        user_barcode    => $userInfo->{'userbarcode'},
        user_username   => $userInfo->{'username'},
        user_firstname  => $userInfo->{'firstname'},
        user_lastname   => $userInfo->{'lastname'},
        homeroom        => $userInfo->{'homeroom'},
        teacher         => $userInfo->{'teacher'},
        grade           => $userInfo->{'grade'},
        notes           => $userInfo->{'notes'},
        hiddenid        => $userInfo->{'uid'},
        balance         => $balance,
    );
}

sub getLoanItemList{
    my($dbh, $template, $uid) = @_;
    my $loanList    = circ_getUserListLoan($dbh, {uid=>$uid});
    my $nCols       = eq_def_colDisplayCount($dbh, {defType=>'item', display=>1});
    my $count = 0;
    my $odCount = 0;
    
    foreach my $loan (@$loanList){
        if ($loan->{'overdue'} ) {$odCount++;}
        $loan->{'number'} = $count++;
        if ($loan->{'dateDue'}){
            $loan->{'dateDueFormat'} = $loan->{'dateDue'};
            $loan->{'dateDueFormat'} =~ s/ / \/ /; 
            $loan->{'dateDueFormat_text'} = date_time_text ($loan->{'dateDue'}, 0, 'en');
            #$dateDueFormat =~ s/([\d]{4}-[\d]{2}-[\d]{2}) ([\d]{2}:[\d]{2}:[\d]{2})/$1 \/ $2/; 
        }
        if ($loan->{'dateLoan'}){
            $loan->{'dateLoanFormat'}  = $loan->{'dateLoan'};
            $loan->{'dateLoanFormat'}  =~ s/ / \/ /; 
            $loan->{'dateLoanFormat_text'} = date_time_text ($loan->{'dateLoan'}, 0, 'en');

        }
    }
    $template->param(
        loanList        => $loanList,
        ncolspan        => $nCols + 4,
        loanCount       => scalar(@$loanList),
        numOfOverdue    => $odCount,
    );
}

sub getReservedItemList{
    my ($dbh,$template,$uid) = @_;
    my $reserveList = circ_getUserListReserve($dbh,$uid);
    my $order = 0;
    foreach my $r (@$reserveList){
        $r->{'order'} = $order++;
         if ($r->{'dateReserve'}){
            $r->{'dateReserveFormat'} = $r->{'dateReserve'};
            $r->{'dateReserveFormat'}  =~ s/ / \/ /; 
            $r->{'dateReserveFormat_text'} = date_time_text($r->{'dateReserve'}, 0, 'en' );
        }
        if ($r->{'dateExpiry'}){
            $r->{'dateExpiryFormat'} = $r->{'dateExpiry'};
            $r->{'dateExpiryFormat'}  =~ s/ / \/ /; 
            $r->{'dateExpiryFormat_text'} = date_time_text($r->{'dateExpiry'}, 0, 'en' );
        }
        if ($r->{'holdExpiry'}){
            $r->{'holdExpiryFormat'} = $r->{'holdExpiry'};
            $r->{'holdExpiryFormat'}  =~ s/ / \/ /; 
            $r->{'holdExpiryFormat_text'} = date_time_text($r->{'holdExpiry'}, 0, 'en' );
        }
    }
    $template->param(
        reserveList     =>  \@$reserveList,
        numOfReserves   =>  scalar(@$reserveList),
    );
}

sub getDeadLineDate{
    my ($length, $dateStr) = @_;
    my $retDate;

    if ($length <= 0){
        return $retDate =  `date -d'+%Y-%m-%d %H:%M:%S'`;
    }
    return $retDate =  `date -d '$length hour' '+%Y-%m-%d %H:%M:%S'`;
}

sub formatStrDateDue{
    my ($n,$h_d) = @_;
    my $retDD;
    return if ($n eq '' || $h_d eq '');
    if ($h_d eq 'd' ){
         $n = $n * 24;
    }
    return $retDD = `date -d '$n hour' '+%Y-%m-%d %H:%M:%S'`;
}

