#!/usr/bin/perl

#use utf8;
use strict;
use CGI;
use JSON;

use Opals::Context;
use Opals::NoticeEmailSvc qw(
    emailSvc_holdReady
);

use Opals::Circulation qw(
    circ_placeReserve
    circ_fillReserve
    circ_placeHold
    circ_getRecInfo
    circ_numItemsAvailable
    circ_cancelReserve
    circ_placeReqRsv
    circ_updateReqRsvStatus
    circ_setHoldExpiry
    circ_suspendReserve
    circ_cancelHoldReserve
);
use Opals::Date qw(
    date_today
    date_now
    date_parse
    date_getDeadLineDate
    date_addDeltaWorkday
);
use Opals::User qw(
    user_getInformationById
);
use Opals::Locale qw(
    loc_getMsgFile
);

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

my $input=getInput();
my $cgi = CGI->new;
use Time::localtime;

my ($errCode, $ck, $resp) = Opals::User::user_currentUser($dbh, $cgi);
my $perm=Opals::User::user_permission_1($dbh,$resp->{'uid'});
my $useHasReservePerm=$perm->{'circ_rsrv'}||0;
my $tm = localtime;
my $todayStr = sprintf("%04d-%02d-%02d", $tm->year+1900, ($tm->mon)+1, $tm->mday);
   
    my $rs={rejected=>[],approved=>[],cancelled=>[],reactivate=>[],ready=>[]};
    my $rejectList      =$input->{"rejectedList"};
    my $approveList     =$input->{"approvedList"};
    my $cancelList      =$input->{"cancelledList"};
    my $suspendedList   =$input->{"suspendedList"};
    my $reactivateList  =$input->{"reactivateList"};
    my $readyList       =$input->{"readyList"};

my $fnMap={
            "rejected"   =>\&save_rejectedList,
            "approved"   =>\&save_approvedList,
            "cancelled"  =>\&save_cancelledList,
            "suspended"  =>\&save_suspendedList,
            "reactivate" =>\&save_reactivateList,
            "ready"      =>\&save_readyList,
            "priority"   =>\&save_priorityList,
            "holdExipry" =>\&update_holdExipryList,
            
};
foreach my $s (qw(rejected approved cancelled suspended reactivate ready priority holdExipry)){
    #only user that has circ_rsrv can change the reserve request
    #user can only cancel his/her own requests or has to have circ_rsrv permission.
    if($useHasReservePerm || $s eq 'cancelled'){
        if(defined $input->{$s."List"} && defined $fnMap->{$s}){
            my $fn=$fnMap->{$s};
            my $reqList=$input->{$s."List"};
            $rs->{$s}=&$fn($dbh,$reqList);
        }
    }

}

#-------------------------------------------------------------
    print "Content-type: text/plain\n\n";
    print  to_json($rs) ;
#-------------------------------------------------------------
sub update_holdExipryList{
    my ($dbh,$holdExipryList)=@_;
    my @rs=();
    foreach my $r (@$holdExipryList){
        $r->{'dateExpiry'} =~ s/(dddd-dd-dd)(.*)/$1/;
        $r->{'dateExpiry'} .=" 23:59:59";
        circ_setHoldExpiry($dbh,$r->{'idReserve'},$r->{'dateExpiry'},$resp->{'uid'});
        push @rs,{id=>$r->{'idReserve'}};
    }
    return \@rs;
}


#-------------------------------------------------------------
sub save_priorityList{
    my ($dbh,$priorityList)=@_;
    my @rs=();
    my $sth         =$dbh->prepare("select idReserve,priority from opl_reserve where rid=? 
                                   && numCopyReserve>0 && dateExpiry>now() && dateCancel is null 
                                   order by priority,idReserve");
    my $sth_update  =$dbh->prepare("update opl_reserve set priority=? where idReserve=?");
    foreach my $r (@$priorityList){
        my $rid=$dbh->selectrow_array("select rid from opl_reserve where idReserve=?",undef,$r->{'idReserve'});
        if($rid){
            my $priority=1;
            my @rp=();
            my $oldPriority=1;
            my $newPriority=$r->{'priority'};
            $sth->execute($rid);
            while(my($id,$p)=$sth->fetchrow_array){
                if($id == $r->{'idReserve'}){
                    $oldPriority =$priority ; 
                }
                push @rp,{id=>$id,priority=>$priority};
                $priority++;
            }
            my ($chkB,$chkE,$inc) =($newPriority,$oldPriority,1);
            if($newPriority > $oldPriority){
                ($chkB,$chkE,$inc) =($oldPriority,$newPriority,-1);
            }
            foreach my $e(@rp){
                if($e->{'id'} == $r->{'idReserve'}){
                    $e->{'priority'}=$newPriority;
                }
                elsif($e->{'priority'}>=$chkB && $e->{'priority'}<=$chkE){
                    $e->{'priority'} +=$inc;
                }
                $sth_update->execute($e->{'priority'},$e->{'id'} );
                push @rs,{id=>$e->{'id'}};

            }
        }
    }
    return \@rs;
}

#-------------------------------------------------------------
sub save_rejectedList{
    my ($dbh,$rejectedList)=@_;
    my @rs=();
    foreach my $req (@$rejectedList){
        circ_updateReqRsvStatus($dbh, $req->{'id'},'reject',undef,$resp->{'uid'});
        push @rs,{id=>$req->{'id'}};
    }
    return \@rs;
}
#-------------------------------------------------------------
sub save_cancelledList{
    my ($dbh,$cancelledList)=@_;
    my @rs=();
    my $timeNow = date_now();
    foreach my $req (@$cancelledList){
        my ($reqUid)=$dbh->selectrow_array("select uid from opL-requestReserve whre id=?",undef,$req->{'id'});
        if($useHasReservePerm ||  $reqUid==$resp->{'uid'}){
            circ_updateReqRsvStatus($dbh, $req->{'id'},'cancel',undef,$resp->{'uid'},undef,$req->{'rNotes'});
            circ_cancelHoldReserve($dbh,$req->{'idReserve'},$timeNow) if(defined $req->{'idReserve'} && $req->{'idReserve'}>0);
            push @rs,{id=>$req->{'id'}};
        }
    }
    return \@rs;
}
#-------------------------------------------------------------
sub save_suspendedList{
    my ($dbh,$suspendedList)=@_;
    my @rs=();
    foreach my $r (@$suspendedList){
        circ_suspendReserve($dbh,$r->{'idReserve'},$r->{'suspendFrom'},$r->{'suspendUntil'},$r->{'note'},$resp->{'uid'} );
        push @rs,{idReserve=>$r->{'idReserve'}};
    }
    return \@rs;
}
    
#-------------------------------------------------------------
sub save_approvedList{
    my ($dbh,$approvedList)=@_;
    my @rs=();
    foreach my $req (@$approvedList){
        my $reserveId=placeReserve($dbh,$req->{'id'});      
        push @rs,{id=>$req->{'id'},idReserve=>$reserveId};
    }
    return \@rs;
}
#-------------------------------------------------------------
sub save_reactivateList{
    my ($dbh,$reactivateList)=@_;
    my @rs=();
    foreach my $req (@$reactivateList){
        circ_updateReqRsvStatus($dbh,$req->{'id'},'reactivate',undef,$resp->{'uid'},$req->{'dateExpiry'},$req->{'rNotes'});
       push @rs,{id=>$req->{'id'}};
    }
    return \@rs;
}
#-------------------------------------------------------------
sub save_readyList{
    my ($dbh,$readyList)=@_;
    my @rs=();
    my $resNoticeMsgMap =loc_getMsgFile('circ/reserveNotice.msg',{});
    foreach my $req (@$readyList){
        circ_updateReqRsvStatus($dbh, $req->{'id'},'ready',undef,$resp->{'uid'});
        my ($userInfo, $guardian) = user_getInformationById($dbh, $req->{'uid'});
        my $itemInfo    =circ_getRecInfo($dbh, $req->{'rid'});
        my $reserveInfo=undef;
        if($req->{'idReserve'}>0){
            $reserveInfo=getReserveInfo($dbh,$req->{'idReserve'});
        }

        my $reqStatus={id=>$req->{'id'},email=>$req->{'email'}};
        if(defined $req->{'emailNotice'} && $req->{'emailNotice'}){
            my $param={
                msg=>$req->{'msg'},
                email=>$req->{'email'},
                emailSubject=>$resNoticeMsgMap->{'eSubjReadyTxt'},
                itemInfo=>$itemInfo,
                reserveInfo=>$reserveInfo,
                userInfo=>$userInfo                 
            };
            $reqStatus->{'sendMailStatus'}=emailSvc_holdReady($dbh,$param);
            if(defined $reqStatus->{'sendMailStatus'} && $reqStatus->{'sendMailStatus'}){
               my $log= to_json({notes=>$req->{'notes'}||'', emailTo=>$req->{'email'}});        
                $dbh->do("insert into opl_reqReserveHistory set reqId=?,uid=?,action=?,log=?"
                    ,undef,$req->{'id'},$resp->{'uid'},"holdReadyEmail",$log);
            }
        }

        push @rs,$reqStatus;
    }
    return \@rs;
}
#-------------------------------------------------------------
sub save_readyList_bk{
    my ($dbh,$readyList)=@_;
    my @rs=();
    foreach my $req (@$readyList){
        $dbh->do("update opl_requestReserve set status=?,dateProcess=now()
                  where id=?",undef,'ready',$req->{'id'});
        my $reqStatus={id=>$req->{'id'},email=>$req->{'email'}};
        my $actionStr="ready";
        my $log= to_json({notes=>$req->{'notes'}||'',dateProcess=>$todayStr});

        if(defined $req->{'emailNotice'} && $req->{'emailNotice'}){
            $reqStatus->{'sendMailStatus'}=emailSvc_holdReady($dbh,$req->{'uid'},$req->{'email'},$req->{'msg'},$req->{'rid'});
            if(defined $reqStatus->{'sendMailStatus'} && $reqStatus->{'sendMailStatus'}){
                $actionStr ="holdReadyEmail";
               # $dbh->do("update opl_requestReserve set dateSentMail=now(), countSentMail=countSentMail+1
               #        where id=?",undef,$req->{'id'});
               my $log= to_json({notes=>$req->{'notes'}||'',dateProcess=>$todayStr});        
                $dbh->do("insert into opl_reqReserveHistory set reqId=?,uid=?,action=?,log=?"
                    ,undef,$req->{'id'},$resp->{'uid'},$actionStr,$log);
            }
        }
        $dbh->do("insert into opl_reqReserveHistory set reqId=?,uid=?,action=?,log=?"
                 ,undef,$req->{'id'},$resp->{'uid'},$actionStr,$log);

        push @rs,$reqStatus;
    }
    return \@rs;
}
    

#-------------------------------------------------------------
sub placeReserve{
    my ($dbh,$id)=@_;
    my ($id,$idReserve,$uid,$rid,$numCopyReserve,$dateExpiry)
            =$dbh->selectrow_array("select id,idReserve,uid,rid,numCopyRequest,dateExpiry 
                                    from opl_requestReserve where id=?",undef,$id);

    if(!defined $idReserve || $idReserve==0){
        my $recInfo  = circ_getRecInfo($dbh, $rid, $uid);
        $idReserve = doReserve($dbh, $id,$uid, $recInfo, $numCopyReserve,$dateExpiry);
    }
    return $idReserve;
}
#-------------------------------------------------------------
sub doReserve{
    my($dbh, $reqId,$uid, $recInfo, $numCopyReserve,$dateExpiry)=@_;
    my $idReserve=0;
    my $rid=$recInfo->{'rid'};
    my $numHold=0;
    my $holdExpiry="";
  
    my $idReserve = circ_placeReserve($dbh, $uid, $rid, $numCopyReserve, $todayStr, $dateExpiry,$resp->{'uid'}, $reqId);
    
    if($idReserve>0 ){
        my $numItemAvailable = circ_numItemsAvailable($dbh,$rid);
        if($numItemAvailable) {
            $holdExpiry = date_getDeadLineDate($recInfo->{'holdPeriod'}, $todayStr);
            my $loopEnd = $numItemAvailable < $numCopyReserve ? $numItemAvailable:$numCopyReserve;
            $numHold=$loopEnd;
            for(my $i=0; $i<$loopEnd;$i++){
                circ_fillReserve($dbh,$uid,$rid);
                circ_placeHold($dbh, $idReserve,$todayStr,$holdExpiry,$resp->{'uid'});
            }
        }
    }
    return ($idReserve);
}
#-------------------------------------------------------------
sub getReserveInfo{
    my ($dbh,$idReserve)=@_;
    my  $reserveInfo=$dbh->selectrow_hashref("select * from opl_reserve where idReserve=?", undef, $idReserve);
    if($reserveInfo){
        my $sth=$dbh->prepare("select * from opl_hold  where  idReserve=? && dateLoan is null 
                               && dateCancel is null && dateExpiry > now() ");
        $reserveInfo->{'holdList'}=[];
        $sth->execute($idReserve);
        while(my $h=$sth->fetchrow_hashref){
             push @{$reserveInfo->{'holdList'}},$h;
        }
    }
    return $reserveInfo;
    
}
#-------------------------------------------------------------

sub getInput{
    my $input ={};
    if ($ENV{'REQUEST_METHOD'} eq "POST") {
        my $json ="";
        while (<STDIN>) {
            $json .= $_;
        }
        $input = decode_json($json);
    }
    return $input;
}


