#!/usr/bin/perl

use strict;
use CGI;
use JSON;
use Opals::Context;

use POSIX qw(

    floor

);

use Opals::User qw(

    user_list
    user_getInformationById
    user_teacherList
    user_isUserBc
);


use Opals::TeacherCourse qw(
    
    teacherCourse_getList
    teacher_getCatCode
    
);

use Opals::Course qw(
    
    course_getSchoolYearList
    course_getSchoolYearInfo

);

use Opals::Tb_Circulation qw(

    circ_getItemStatus
    circ_getItemInfo
    circ_getUserCircStatus
    circ_getUserListLoan
    circ_processLoan
    circ_processReturn
    circ_processRenew
    circ_declareLost
    circ_setAvailable
    circ_record_ODL
    circ_getActiveLoanId
);

use Opals::Tb_Transactions qw(
    trans_doReverseLost
);

use Date::Calc qw(
    Add_Delta_DHMS
);

use Opals::Date qw(
    date_now
    date_time_text
    date_text
    date_today
    date_parse
    date_getDeadLineDate
);

use Opals::Constant;

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

my $cgi = CGI->new;
my $input = {}; 
my ($msgCode,$itemMsgCode,$processCode,$userMsgCode)=(undef,undef,undef,undef);
my ($uid,$barcode,$loanType,$dueDate,$cmdCode,$op,$cmdCode);
my $tmpUser;
my $reqItem;
my $dateDueFormat_text="";
my $todayStr   = date_now();
my ($errCode, $ck, $user) = Opals::User::user_currentUser($dbh, $cgi);
my $loginuid   = $user->{'uid'};

if ($ENV{'REQUEST_METHOD'} eq "POST") {
    $input = decode_json($cgi->param('POSTDATA'));
    my $teacherId   =  $input->{'teacher'}->{'tId'} || 0;
    my $teacherFirstName = $input->{'teacher'}->{'firstname'} || "";
    my $teacherLastName = $input->{'teacher'}->{'lastname'} || "";
    my $teacherName = ($teacherFirstName || $teacherLastName)? $teacherFirstName . "," . $teacherLastName:"";
    my $courseTeacherId = $input->{'course'}->{'tsId'} || 0;
    my $courseId  = $input->{'course'}->{'courseId'} | 0;
    my $courseName  = $input->{'course'}->{'courseName'} || "";
    my $courseCode  = $input->{'course'}->{'courseCode'} || "";
    $uid = $input->{'uid'};
    $barcode = $input->{'barcode'};
    $barcode =~ s/^\s+|\s+$//g;
    $loanType = $input->{'loanType'};
    $dueDate = ($loanType eq 'standard')?"": $input->{'dateDue'} || $input->{'hourDue'};
    $op = $input->{'op'} || "";
    $cmdCode = $input->{'cmdCode'} || "";
    my $loanOverride     = 0;
    my ($userInfo, $guardian) = user_getInformationById($dbh,$uid);
    my $userStatus      = circ_getUserCircStatus($dbh, $uid, $barcode);
    my $itemCircStatus  = circ_getItemStatus($dbh, $barcode);
    my $itemInfo        = circ_getItemInfo($dbh,$barcode,$uid);    
    $userMsgCode     = getMsgCode_user($userStatus);
    $itemMsgCode     = getMsgCode_item($itemCircStatus, $uid);
    if ($itemCircStatus->{'status'} == IT_STAT_NOEXIST){
        $msgCode = 1;
        #check if enter userbarcode into item barcode input
        my $isUId = user_isUserBc($dbh,$barcode);
        if ($isUId){
            $itemMsgCode='19';
            $uid = $isUId;
        }
    }
    else {
        $reqItem = $itemInfo;
        my $loanPeriod = ($itemInfo->{'loanPeriod'})? $itemInfo->{'loanPeriod'} :0;
        if ($dueDate && $dueDate ne ''){
            my $dd = date_parse($dueDate);
            #if($dd && $dd <$todayStr){
            #    $dueDate="";
            #}
        }
        if (!$dueDate || $dueDate eq ''){
            $dueDate = date_getDeadLineDate($loanPeriod, $todayStr);
        }
        else{
             $dueDate .= " 23:59:59";
        }
        $dateDueFormat_text =  date_time_text($dueDate, 1, 'en' );
        if(($itemMsgCode ne '00')&&($itemInfo->{'loanPeriod'}==0 || $dueDate eq "")){
            $msgCode = 1;
            $itemMsgCode ='02';
        }
        elsif ($itemCircStatus->{'status'} != IT_STAT_NOEXIST && $itemInfo){
            my $loanId;
            my $allowOD = 0;
            #0: no override, 1: override with question, 2: override automatically without approval
            my $msgCode='';
            if (($itemMsgCode eq '05' || $itemMsgCode eq '08' || 
                $itemMsgCode eq '12' || $itemMsgCode eq '16' ||
                $itemMsgCode eq '17') && (substr($userMsgCode , 0 ,3 ) eq '100' )){
                ($processCode,$loanId) = processCmd($dbh,$uid,$barcode,$itemInfo,$itemCircStatus,$itemMsgCode,$dueDate,$courseTeacherId,$teacherName,$courseName );
            }
            elsif ($cmdCode && $cmdCode ne ''){
                if ($cmdCode eq '11' || $cmdCode eq '15'){ #renewal
                }
                ($processCode,$loanId) = processCmd($dbh,$uid,$barcode,$itemInfo,$itemCircStatus,$cmdCode,$dueDate);
            }
            elsif ($itemCircStatus->{'status'} != IT_STAT_NOEXIST){
                my $maxLoanBit = substr( $userMsgCode, 2, 1);
                my $overdueBit = substr( $userMsgCode, 1, 1);
                if(substr($loanOverride, 1, 1) eq '1'){
                    $allowOD = 2;
                }
                if($maxLoanBit eq '1'){
                    if(substr($loanOverride, 2, 1) eq '1' ){
                         ($processCode,$loanId)= processCmd($dbh,$uid,$barcode,$itemInfo,$itemCircStatus,$itemMsgCode,$dueDate,$courseTeacherId,$teacherName,$courseName );      
                    }
                    else{
                        $msgCode        = $itemMsgCode ."-" . $userMsgCode;
                    }
                }
                elsif($overdueBit eq '1' && $allowOD == 0){
                    $processCode='0';
                }
                elsif($overdueBit eq '1' && $allowOD == 2){
                    ($processCode,$loanId) = processCmd($dbh,$uid,$barcode,$itemInfo,$itemCircStatus,$itemMsgCode,$dueDate,$courseTeacherId,$teacherName,$courseName );
                    }
                else{
                    $msgCode =$itemMsgCode ."-" . $userMsgCode;
                    }
            }
        }
    }

}#$ENV{'REQUEST_METHOD'} eq "POST"
print "Content-type: text/plain\n\n";
print  to_json({
    msgCode       => $msgCode,
    itemMsgCode   => $itemMsgCode,
    itemInfo      => $reqItem,
    processCode   => $processCode,
    userMsgCode   => $userMsgCode,
    uid           => $uid,
    dueDate       => $dateDueFormat_text,
    barcode       => $barcode,
});
#--------------------------------------------------------------------------------
sub getMsgCode_user{
    my($userStatus)=@_;
    return $userStatus->{'status'}.$userStatus->{'overdue'}.$userStatus->{'maxLoan'}.$userStatus->{'maxRenew'}.$userStatus->{'maxReserve'};
}
#--------------------------------------------------------------------------------
sub getMsgCode_item{
    my ($itemCircStatus,$uid)=@_;
    my $retCode="";
    my $reserveList=$itemCircStatus->{'reserveList'};
    my $holdList=$itemCircStatus->{'holdList'};
    if($itemCircStatus->{'status'}==IT_STAT_NOEXIST){
        $retCode="00";    }
    elsif($itemCircStatus->{'status'}==IT_STAT_UNAVAIL){
        $retCode="01";    }
    elsif($itemCircStatus->{'status'}==IT_STAT_RESTRICTED){
        $retCode="02";    }
    elsif($itemCircStatus->{'status'}==IT_STAT_LOST){
        $retCode="03";    }
    elsif($itemCircStatus->{'status'}==IT_STAT_MISSING){
        $retCode="18";    }
    elsif($itemCircStatus->{'status'}==IT_STAT_DAMAGED){
        $retCode="04";    }
    elsif($itemCircStatus->{'status'}==IT_STAT_ONHOLD){
           if(getReserveId($uid,$holdList)>0){
               $retCode="05";}
           elsif(getReserveId($uid,$reserveList)>0){
                $retCode="06";}
           else{
                $retCode="07";}
    }
    elsif($itemCircStatus->{'status'}==IT_STAT_FULL_AVAIL && getReserveId($uid,$holdList)>0 ){
          $retCode="05";
    }    
    elsif($itemCircStatus->{'status'}==IT_STAT_HAVE_RSVR ){
        if(scalar(@$reserveList)){
            my $topReserveUID = @$reserveList[0]->{'uid'};
            if($itemCircStatus->{'inTBKRoom'}){
                if($uid ==$topReserveUID){
                    $retCode="08";            }
                elsif(getReserveId($uid,$reserveList)>0){
                    $retCode="09";            }
                else{
                    $retCode="10";            }
            }
            else{
                if($uid == $itemCircStatus->{'l_uid'}){
                    $retCode="11";  
                }
                elsif($uid ==$topReserveUID){
                    $retCode="12";            }
                elsif(getReserveId($uid,$reserveList)>0){
                    $retCode="13";            }
                else{
                    $retCode="14";            }
            }
        }
    }
    elsif($itemCircStatus->{'status'}==IT_STAT_ONLOAN && $uid eq $itemCircStatus->{'l_uid'}){
        $retCode="15";    }
    elsif($itemCircStatus->{'status'}==IT_STAT_ONLOAN && $uid ne $itemCircStatus->{'l_uid'}){
        $retCode="16";    }
    else{ # fully available
        $retCode="17";    }
    return $retCode;    
}
#--------------------------------------------------------------------------------
sub processCmd{
    my ($dbh, $uid,$barcode,$itemInfo,$itemCircStatus,$cmdCode,$dueDate, $teacherScheduleId,$teacherName,$courseName) =@_;
    my $dateReturn =$todayStr;
    my ($loanId, $retVal); 
    
    my ($loanId, $retVal); 
    if ($cmdCode eq '03'){
        circ_setAvailable($dbh,$barcode,IT_STAT_LOST);       
        trans_doReverseLost($dbh,$barcode,$loginuid);
    }
    if ($cmdCode eq '18'){
        circ_setAvailable($dbh,$barcode,IT_STAT_MISSING);       
    }
    elsif ($cmdCode eq '04'){
        circ_setAvailable($dbh,$barcode,IT_STAT_DAMAGED);       
    }    
    elsif($cmdCode eq '05'){  
        #my $idReserve =getReserveId($uid,$itemCircStatus->{'holdList'});
        #my $fillHold  = circ_fillHold($dbh,$idReserve,$barcode);
    }
    elsif($cmdCode eq '06'){
        #my $idReserve     = getReserveId($uid,$itemCircStatus->{'reserveList'});
        #my $fillReserve   = circ_fillReserve($dbh,$uid ,$itemCircStatus->{'rid'});
        #my $idReserve     = getLastReserveId($itemCircStatus->{'holdList'});
        #my $cancelHold    = circ_cancelHold($dbh,$idReserve) ;
        #my $resetReserve  = circ_resetReserve($dbh,$idReserve);
    }
    elsif($cmdCode eq '07'){
        #my $idReserve    = getLastReserveId($itemCircStatus->{'holdList'});
        #my $cancelHold   = circ_cancelHold($dbh,$idReserve) ;
        #my $resetReserve = circ_resetReserve($dbh,$idReserve);
    }
    elsif($cmdCode eq '07_R'){
=item
        #my $dateExpiry   = date_getDeadLineDate($itemInfo->{'reservePeriod'},$todayStr);
        #my $putReserve   = circ_placeReserve($dbh, $uid,$itemCircStatus->{'rid'},1, $todayStr, $dateExpiry);
        #$retVal =  "p1_07_R";
=cut
        return ($retVal,$loanId);
    }
    elsif($cmdCode eq '08' || $cmdCode eq '09'){
        #my $fillReserve  = circ_fillReserve($dbh,$uid ,$itemCircStatus->{'rid'});
    }
    elsif($cmdCode eq '09_H'){
=item
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_09_H";
=cut
        return ($retVal,$loanId);
     }
    elsif($cmdCode eq '10_H'){
=item
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_10_H";
=cut
        return ($retVal,$loanId);
    }
    elsif($cmdCode eq '10_HR'){
=item
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
           $dateExpiry   = date_getDeadLineDate($itemInfo->{'reservePeriod'},$todayStr);
        my $putReserve   = circ_placeReserve($dbh, $uid,$itemCircStatus->{'rid'},1, $todayStr, $dateExpiry);
        $retVal =  "p1_10_HR";
=cut
        return ($retVal,$loanId);
    }
    elsif($cmdCode eq '11' || $cmdCode eq '15'){
        my $renew       = circ_processRenew($dbh,$uid,$barcode,$dueDate);
        $retVal =  "p". $renew . "_" .$cmdCode;
        $loanId=circ_getActiveLoanId($dbh,$barcode,$uid);
        return ($retVal,$loanId) ;
    }
    elsif($cmdCode eq '11_H' ){
=item
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_11_H";
=cut
        return ($retVal,$loanId);
    }
    elsif($cmdCode eq '12' || $cmdCode eq '13'){
=item
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $fillReserve  = circ_fillReserve($dbh,$uid ,$itemCircStatus->{'rid'});
=cut
    }
    elsif($cmdCode eq '13_H'){
=item
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_13_H";
=cut
        return  ($retVal,$loanId);
    }
    elsif($cmdCode eq '14' || $cmdCode eq '16'){
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
    }
    elsif($cmdCode eq '14_H'){
=item
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
        $retVal =  "p1_14_H";
=cut
        return ($retVal,$loanId);
    }
    elsif($cmdCode eq '14_HR'){
=item        
        my $return       = doReturn($dbh,$itemCircStatus->{'l_uid'}, $barcode,$dateReturn);
        my $reserveList  = $itemCircStatus->{'reserveList'};
        my $idReserve    = @$reserveList[0]->{'idReserve'};
        my $uidReserve   = @$reserveList[0]->{'uid'};
        my $reserveExpiry= @$reserveList[0]->{'dateExpiry'};
        my $dateExpiry   = date_getDeadLineDate($itemInfo->{'holdPeriod'},$todayStr);
        if($dateExpiry >$reserveExpiry){
            $dateExpiry  = $reserveExpiry;
        }
        circ_fillReserve($dbh,$uidReserve ,$itemCircStatus->{'rid'});
        my $putOnHold    = circ_placeHold($dbh, $idReserve,$todayStr,$dateExpiry);
           $dateExpiry   = date_getDeadLineDate($itemInfo->{'reservePeriod'},$todayStr);
        my $putReserve   = circ_placeReserve($dbh, $uid,$itemCircStatus->{'rid'},1, $todayStr, $dateExpiry);
        $retVal =  "p1_14_HR";
=cut
        return ($retVal,$loanId);
    }
#   2006-09-28
#   fill hold if item is availbale and on hold for the same patron        
#   BEGIN    
=item
    my $idReserve =getReserveId($uid,$itemCircStatus->{'holdList'});
    if($idReserve && ($cmdCode eq '16' || $cmdCode eq 17)){
            my $fillHold  = circ_fillHold($dbh,$idReserve,$barcode);
    }
=cut
#   END     
    my $loan = circ_processLoan($dbh,$uid ,$barcode,$todayStr,$dueDate, $itemInfo->{'maxRenewal'}, $itemInfo->{'fine'},$teacherScheduleId,$teacherName,$courseName);
    $loanId=circ_getActiveLoanId($dbh,$barcode,$uid);

    $retVal = "p" .$loan  ."_" .$cmdCode ;

    return ($retVal,$loanId);
}
sub getReserveId{
    my($uid,$list)=@_;
    if(!$list){
        return 0;
    }
    for(my $i=0; $i < scalar(@$list); $i++){
        if(@$list[$i]->{'uid'} == $uid){
            return @$list[$i]->{'idReserve'};
        }
    }
    return 0;
}
sub doReturn{
    my ($dbh, $uid, $barcode, $dateReturn) = @_;
    return circ_processReturn($dbh, $uid, $barcode, $dateReturn);
}

