#!/usr/bin/perl

#use utf8;
use strict;
use CGI;

use Opals::Context;
use Opals::Constant;
use Opals::Date qw(
    date_text
    date_DHM_text
);
use Opals::Template qw(
    tmpl_read
    tmpl_write
    tmpl_preference
);
use Opals::Search qw(
    srch_searchRecord
);
use Opals::MarcXml qw(
    mxml_updateDbZebra
    mxml_updateItemStatus
);
use Opals::Circulation qw(
    Circ_validateFollettBarcode
    Circ_validateSpectrumBarcode
    Circ_validateLeadingZeroBc
);
use Opals::Locale qw(
    loc_getMsgFile
    loc_setMsgValue
    loc_write
);
use Opals::Transactions qw(
    trans_doReverseLost
);
use Opals::BarcodeMgmt qw(
    bcm_validateBc
);
use POSIX qw(
    ceil
);


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

my $cgi = CGI->new;
my $input = $cgi->Vars();
my $syspref = tmpl_preference($dbh);
my $validateBc = $syspref->{'validateBarcode'};
my $barcodeType = $syspref->{'barcodeType'};
my $patronItemPrivacy=$syspref->{'patronItemPrivacy'};
my ($permission, $cookie, $template) = tmpl_read(
        {
            dbh             => $dbh,
            cgi             => $cgi,
            tmplFile        => 'circ/loan_itemStatus.tmpl',
            reqPermission   => 'marc_edit|circ_loan|circ_return|circ_rsrv',
        }
);



my $bc = $input->{'bc'};
$bc    =~ s/^\s+|\s+$//g;

#Thu, Jan 14, 2010 @ 16:01:09 EST
my $borrower;
my $dateStatus=undef;
$template->param(patronItemPrivacy => $patronItemPrivacy);


$bc= bcm_validateBc($dbh,$bc,$barcodeType) if($validateBc eq '1');
    my $rid;
if ($bc) {
    $template->param(bc => $bc);
    my $sth = $dbh->prepare(<<_STH_);
select  r.rid, r.title, r.author, r.pubName, r.pubDate,i.callNumber,i.location
from    opl_item as i, opl_marcRecord as r
where   i.barcode = ? &&
        i.rid = r.rid
_STH_

    $sth->execute($bc) || return;
    my $rec = $sth->fetchrow_hashref;
    $sth->finish;

    if ($rec) {
        $rid = $rec->{'rid'};
        $rec->{'callNumber'}=undef if($rec->{'callNumber'} eq'');
        $template->param($rec);
    }
    else {
        $template->param(error => 1);
    }

    if ($input->{'op'}) {
        SaveStatus($template, $dbh, $input);
    }
    GetBorrower($template, $dbh, $bc);
    
}
$template->param(circulation =>1);

   my $msgValMap={  msg_04=>{lastname=>$borrower->{'loan_lastname'} , 
                             firstname=>$borrower->{'loan_firstname'},
                             loanDate=>$borrower->{'loan_dateLoan'} },
#                    msg_05=>{lastname=>$borrower->{'hold_lastname'}, 
#                             firstname=>$borrower->{'hold_firstname'},
#                             holdDateStart=>$borrower->{'hold_dateHold'},
#                             holdDateEnd=>$borrower->{'hold_dateExpiry'}                            
#                              },
#                    msg_07=>{lastname=>$borrower->{'rsvr_lastname'},
#                             firstname=>$borrower->{'rsvr_firstname'},
#                             reserveDate=>$borrower->{'rsvr_dateReserve'},
#                             reserveExpire=>$borrower->{'rsvr_dateExpiry'}},

                    msg_09=>{dateStatus=>$dateStatus},
                             
                    msg_10=>{lastname=>$borrower->{'LastName'},
                             firstname=>$borrower->{'FirstName'}},
                             
                    msg_12=>{lastname=>$borrower->{'LastName'},
                             firstname=>$borrower->{'FirstName'}},

                    msg_13=>{dateStatus=>$dateStatus}
                             
                   
                    };
    my $itemStatusMsgMap =loc_getMsgFile('circ/itemStatus.msg',$msgValMap);
    my $holdMsg=$itemStatusMsgMap->{"msg_05b"};
    my $hList=GetHoldList($dbh,$bc);
    my @holdList=();
    foreach my $hold(@$hList){
       push @holdList,  {holdFor=>loc_setMsgValue( $holdMsg,{lastname=>$hold->{'lastname'}, 
                                                   firstname=>$hold->{'firstname'},
                                                   holdDateStart=>$hold->{'dateHold'},
                                                   holdDateEnd=>$hold->{'dateExpiry'}
                                       })};
    }

    my $reserveMsg=$itemStatusMsgMap->{"msg_07b"};
    my $rList=GetReserveList($dbh,$rid);
    my @reserveList=();
    foreach my $reserve(@$rList){
       push @reserveList,  {reserveTo=>loc_setMsgValue( $reserveMsg,{lastname=>$reserve->{'lastname'},
                                                                     firstname=>$reserve->{'firstname'},   
                                                                     reserveDate=>$reserve->{'dateReserve'},
                                                                     reserveExpire=>$reserve->{'dateExpiry'}                                       
                                                                     })};
    }    
    $template->param(reserveList =>\@reserveList);

    loc_write($template,$itemStatusMsgMap);
    $template->param(holdList =>\@holdList);
$template->param(hlpUrl     => Opals::Constant->getHlpUrl('circ_itemonloan') );

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

#########################################################################

sub validateBc{
    my($dbh,$barcode,$barcodeType) =@_;
   if($barcodeType eq '1'){#follett
        $barcode  = Circ_validateFollettBarcode($dbh,$barcode );
    }
    elsif($barcodeType eq '2'){#spectrum
        $barcode  = Circ_validateSpectrumBarcode($dbh,$barcode );
    }
    elsif($barcodeType eq '3'){#leading zero
        $barcode  = Circ_validateLeadingZeroBc($dbh,$barcode );
    }

    #else{#follett
    #    $barcode  = Circ_validateFollettBarcode($dbh,$barcode );
    #}
    return $barcode;
   
}

#----------------------------------------------------------
sub SaveStatus
{
    my ($template, $dbh, $input) = @_;

    my $sql = "select idloan, dateLoan, dateDue, dateReturn, u.uid as uid, 
                firstname, lastname, userbarcode, username
        from opl_loan as l, opl_user as u where l.uid=u.uid 
        and barcode=? order by dateLoan desc";

    my $query = $dbh->prepare($sql);
    $query->execute($input->{'bc'});

    my $rec = $query->fetchrow_hashref;
    $query->finish;

    my $newstatus = 0;
    $newstatus = ITEM_INACTIVE if ( $input->{'itemstatus'} eq 'inactive' );
    $newstatus = ITEM_ACTIVE if ( $input->{'itemstatus'} eq 'active' );
    $newstatus = ITEM_DAMAGED if ( $input->{'itemstatus'} eq 'damaged' );
    $newstatus = ITEM_LOST if ( $input->{'itemstatus'} eq 'lost' );
    # Cannot make an item inactive when it is being on loan
    if ( $rec && !$rec->{'dateReturn'} && $newstatus == ITEM_ACTIVE )
    {
        $template->param(InActiveLoanItem => 1);
        return;
    }

    my ($status, $circ, $firstname, $lastname,$dateStatus) = GetStatusDate($dbh, $bc);
    my $loginuid = $ENV{'curUserId'};
    trans_doReverseLost($dbh,$bc,$loginuid) if($status == ITEM_LOST && $newstatus == ITEM_ACTIVE);
    # Status of item lost by a borrower can't be changed
    if ( $status == ITEM_LOST && $circ )
    {
        if ( $newstatus != ITEM_ACTIVE  ) 
        {
            $template->param(ChangeLostItem => 1);
            return;
        }
    }
 
        
    #----------- Store into database the new item type, the new status for this item
    $sql = "update opl_item set typeId=?, available=? where barcode=?";
    $query = $dbh->prepare($sql);
    my $avail = ( $newstatus == ITEM_ACTIVE ) ? 1 : 0;
    my $typeId = $input->{'typeId'};
    $query->execute($typeId, $avail, $input->{'bc'});
    $sql ="update opl_itemInfo set sf852Data=? where sf852Code='3' && barcode=?";
    $query = $dbh->prepare($sql);
    $query->execute($typeId, $input->{'bc'});
    $query->finish;
    #----------- Store into zebra the new item type for this item
    $query = $dbh->prepare("select rid from opl_item where barcode=?");
    $query->execute($input->{'bc'});
    my ($rid) = $query->fetchrow_array;
    $query->finish;
    my $xml=getMarcXml($rid);      
    my $f852 = ''; 
    $xml =~ s/<\?xml version="1.0" encoding="UTF-8"\?>[\r\n]*//gm;
    while ($xml =~ s/([\s]*<datafield tag="852" ind1="[\d ]" ind2="[\d ]">\n([\s]*<subfield code="[\w-]">.*<\/subfield>\n)*[\s]*<\/datafield>[\r\n]*)//)
    {
        my ($fsub, $ftmp) = ($1, $1);
        if ($fsub =~ s/<subfield code="p">(.*)<\/subfield>//)
        {
            my $bc = $1;
            $bc =~ s/ *[:\/] *$//;
            if ( $bc eq $input->{'bc'} )
            {
                $fsub = $ftmp;
                if ( $fsub =~ m/<subfield code="3">(.*)<\/subfield>/ )
                {
                    $fsub =~ s/<subfield code="3">(.*)<\/subfield>/_asdf_/;
                }
                else
                {
                    $fsub =~ s/<\/datafield>/    _asdf_<\/datafield>/;
                }
                $fsub =~ s/_asdf_/<subfield code="3">$typeId<\/subfield>/;
            }
            else { $fsub = $ftmp; }
        }
        $f852 .= $fsub;
    }
    $f852 .= '</record>';
    $xml =~ s/<\/record>/$f852/;
    mxml_updateDbZebra($dbh, $rid, $xml);


    #---------- Store new status of this item
    if ( $newstatus == ITEM_DAMAGED && $status == ITEM_DAMAGED && $circ )
    {
        $template->param(ChangeDamagedItem => 1);
    }
    else
    {   
        if ( $status != $newstatus )
        {
            #$query = $dbh->prepare("insert into opl_itemstatus set barcode=?, ondate=now(), status=?");
            #$query->execute($input->{'bc'}, $newstatus);
            #$query->finish;
            mxml_updateItemStatus($dbh,$input->{'bc'},$newstatus,'');

            if ( ($newstatus == ITEM_ACTIVE || $newstatus == ITEM_DAMAGED) 
                && ($status == ITEM_LOST || $status == ITEM_INACTIVE ) )
            {
                $query = $dbh->prepare("insert into opl_found set barcode=?, ondate=now()");
                $query->execute($input->{'bc'});
                $query->finish;
            }
        }
    }
}
#----------------------------------------------------------
sub getMarcXml{
    my($rid)=@_;
    my $zRoot   = Opals::Context->config('zRoot');
    my $zPort   = Opals::Context->config('zPort');
    my $zDatabase = Opals::Context->config('zDatabase');

    my $dir = "$zRoot/$zPort/record/$zDatabase/" . ceil($rid/1000);
    my $xml="";
    open IN, "<$dir/$rid.xml";
    while (<IN>){$xml .= $_;}
    close IN;
    return $xml

}

#----------------------------------------------------------
sub GetBorrower
{
    my ($template, $dbh, $bc) = @_;

    my $sql = "select * from opl_item where barcode='$bc'";
    my $query = $dbh->prepare($sql);
    $query->execute();
    my $recItem = $query->fetchrow_hashref;
    $query->finish;

# Get loan info 
    my @borrowers = (); 
    $sql = "select idloan, dateLoan, dateDue, dateReturn, o.ondate, u.uid uid, firstname, lastname, 
                userbarcode, username ,if(o.type='lost',1,0) isLost      
    from opl_loan as l inner join opl_user as u using(uid) left outer join opl_odl o using(idloan)  
    where barcode=? order by dateLoan desc";
    
    
    $query = $dbh->prepare($sql);
    $query->execute($bc);
    
    my $rec;
    for (my $i=0; $i<4; $i++)
    {
        my $rec = $query->fetchrow_hashref;
        last if ( !$rec );

        $rec->{'dateLoan'} = date_DHM_text($rec->{'dateLoan'}, 0);
        $rec->{'dateDue'} = date_DHM_text($rec->{'dateDue'}, 0);
        if ( $rec->{'dateReturn'} )
        { 
            $rec->{'dateReturn'} = date_DHM_text($rec->{'dateReturn'}, 0);
        }
        push @borrowers, $rec; 
    }
    $query->finish;
  


   
    $template->param(brwrlist => \@borrowers);
    if ( scalar(@borrowers) > 0 && !$borrowers[0]->{'dateReturn'})
    {
        $template->param(
            loan_userbarcode => $borrowers[0]->{'userbarcode'},
            loan_username    => $borrowers[0]->{'username'},
            loan_firstname   => $borrowers[0]->{'firstname'},
            loan_lastname    => $borrowers[0]->{'lastname'},
            loan_uid    => $borrowers[0]->{'uid'},
            loan_dateLoan    => $borrowers[0]->{'dateLoan'},
            loan_dateDue     => $borrowers[0]->{'dateDue'},
            loan_dateReturn  => $borrowers[0]->{'dateReturn'},
            );
        $template->param(loaning => 1);
        $borrower->{'loan_userbarcode'} =$borrowers[0]->{'userbarcode'};
        $borrower->{'loan_username'} =$borrowers[0]->{'username'};
        $borrower->{'loan_firstname'} =$borrowers[0]->{'firstname'};
        $borrower->{'loan_lastname'} =$borrowers[0]->{'lastname'};
        $borrower->{'loan_uid'} =$borrowers[0]->{'uid'};
        $borrower->{'loan_dateLoan'} =$borrowers[0]->{'dateLoan'};
        $borrower->{'loan_dateDue'} =$borrowers[0]->{'dateDue'};
        $borrower->{'loan_dateReturn'} =$borrowers[0]->{'dateReturn'};

    }

# Get hold info
#    $sql = "select dateHold, h.dateExpiry as dateExpiry, u.uid as uid, 
#                firstname, lastname, userbarcode, username
#        from opl_hold as h, opl_reserve as r, opl_user as u
#        where h.idReserve=r.idReserve and r.uid=u.uid and h.barcode='$bc'
#            and h.dateCancel is null and h.dateLoan is null
#            and to_days(h.dateExpiry) >= to_days(now())";
$sql ="select h.* , u.uid as uid, 
                firstname, lastname, userbarcode, username 
from (opl_reserve as r inner join opl_item as i on r.rid=i.rid ) 
inner join opl_hold as h on h.idReserve=r.idReserve  inner join opl_user as u ON r.uid=u.uid
where i.barcode = ?
AND h.dateExpiry> now() 
AND h.dateCancel is null 
AND h.dateLoan is null
order by dateReserve";

    $query = $dbh->prepare($sql);
    $query->execute($bc);
    
    $rec = $query->fetchrow_hashref;
    $query->finish;

    if ( $rec )
    {
        $rec->{'dateHold'} = date_text($rec->{'dateHold'}, 0);
        $rec->{'dateExpiry'} = date_text($rec->{'dateExpiry'}, 0);
        $template->param(
            hold_userbarcode => $rec->{'userbarcode'},
            hold_username    => $rec->{'username'},
            hold_firstname   => $rec->{'firstname'},
            hold_lastname    => $rec->{'lastname'},
            hold_uid    => $rec->{'uid'},
            hold_dateHold    => $rec->{'dateHold'},
            hold_dateExpiry  => $rec->{'dateExpiry'},
            );
        $template->param(holding => 1);

        $borrower->{'hold_userbarcode'} =$rec->{'userbarcode'};
        $borrower->{'hold_username'}    =$rec->{'username'};
        $borrower->{'hold_firstname'}   =$rec->{'firstname'};
        $borrower->{'hold_lastname'}    =$rec->{'lastname'};
        $borrower->{'hold_uid'}         =$rec->{'uid'};
        $borrower->{'hold_dateHold'}    =$rec->{'dateHold'};
        $borrower->{'hold_dateExpiry'}  =$rec->{'dateExpiry'};

    }


# Get reserve info
    $sql = "select  r.*,u.* from opl_reserve as r inner join opl_user as u on r.uid=u.uid
            where r.rid=?  && r.dateCancel is null && r.dateExpiry > now() && numcopyreserve>0 
            order by dateReserve limit 1;";

    $query = $dbh->prepare($sql);
    $query->execute($recItem->{'rid'});
    
    $rec = $query->fetchrow_hashref;
    $query->finish;

    if ( $rec )
    {
        $rec->{'dateReserve'} = date_text($rec->{'dateReserve'}, 0);
        $rec->{'dateExpiry'} = date_text($rec->{'dateExpiry'}, 0);
        $template->param(
            rsvr_userbarcode => $rec->{'userbarcode'},
            rsvr_username    => $rec->{'username'},
            rsvr_firstname   => $rec->{'firstname'},
            rsvr_lastname    => $rec->{'lastname'},
            rsvr_uid    => $rec->{'uid'},
            rsvr_dateReserve => $rec->{'dateReserve'},
            rsvr_dateExpiry  => $rec->{'dateExpiry'},
            );
        $template->param(reserving => 1);  
        $borrower->{'rsvr_userbarcode'} =$rec->{'userbarcode'};
        $borrower->{'rsvr_username'} =$rec->{'username'};
        $borrower->{'rsvr_firstname'} =$rec->{'firstname'};
        $borrower->{'rsvr_lastname'} =$rec->{'lastname'};
        $borrower->{'rsvr_uid'} =$rec->{'uid'};
        $borrower->{'rsvr_dateReserve'} =$rec->{'dateReserve'};
        $borrower->{'rsvr_dateExpiry'} =$rec->{'dateExpiry'};

    }

# Get list of item types
    $query = $dbh->prepare("select * from opl_itemType");
    $query->execute();

    my @itemTypes = ();
    while ($rec = $query->fetchrow_hashref) {
        if ($rec->{'id'} eq $recItem->{'typeId'}) {
            $rec->{'sel'} = 1;
        }
        push @itemTypes, $rec;
    }
    $query->finish;
    $template->param(itemTypes => \@itemTypes);


# Get the total times of loans/reserves
    $sql = "select count(*) as total from opl_loan where barcode='$bc'";
    $query = $dbh->prepare($sql);
    $query->execute();
    $rec = $query->fetchrow_hashref;
    $template->param(totalLoan => $rec->{'total'});
    $query->finish;
    
    $sql = "select count(*) as total from opl_reserve where rid=?";
    $query = $dbh->prepare($sql);
    $query->execute($recItem->{'rid'});
    $rec = $query->fetchrow_hashref;
    $template->param(totalReserve => $rec->{'total'});
    $query->finish;

# Set status of item
    if ( $recItem->{'available'} == 1 ) 
    { 
        $template->param(itemactive => 1); 
    }
    else
    {
        my ($status, $circ, $firstname, $lastname,$ondate) = GetStatusDate($dbh, $bc);
        $dateStatus=$ondate;
        if ( $status == ITEM_LOST ) { $template->param(itemlost => 1); }
        elsif ( $status == ITEM_DAMAGED ) { $template->param(itemdamage => 1); }
        elsif ( $status == ITEM_INACTIVE ) { $template->param(iteminactive => 1); }
        
        if ( !$circ ) { $template->param(nocirc => 1); }
        $template->param(FirstName => $firstname);
        $template->param(LastName => $lastname);
        $borrower->{'FirstName'}=$firstname;
        $borrower->{'LastName'}=$lastname;

    }
}


#----------------------------------------------------------
sub GetHoldList
{
    my ($dbh, $bc) = @_;
    my @holdList=();
    my $sth = $dbh->prepare(<<_SQL_);
select h.* , u.uid as uid, firstname, lastname, userbarcode, username 
from (opl_reserve as r inner join opl_item as i on r.rid=i.rid ) 
inner join opl_hold as h on h.idReserve=r.idReserve  inner join opl_user as u ON r.uid=u.uid
where i.barcode = ?
AND h.dateExpiry> now() 
AND h.dateCancel is null 
AND h.dateLoan is null
order by  lastname,firstname
_SQL_
    
    $sth->execute($bc);
    

    while ( my $hold =$sth-> fetchrow_hashref)
    {
       $hold->{'dateHold'} = date_text($hold->{'dateHold'}, 0);
       $hold->{'dateExpiry'} = date_text($hold->{'dateExpiry'}, 0);
       push @holdList,$hold;
    }
    $sth->finish;
   return \@holdList;
}
#----------------------------------------------------------
sub GetReserveList
{
    my ($dbh, $rid) = @_;
    my @reserveList=();
    my $sth = $dbh->prepare(<<_SQL_);
select  r.*,u.* 
from    opl_reserve as r inner join opl_user as u on r.uid=u.uid
where   r.rid=?  && r.dateCancel is null && r.dateExpiry > now() && numcopyreserve>0 
order by dateReserve,idReserve
_SQL_
    
    $sth->execute($rid);
    while ( my $reserve =$sth-> fetchrow_hashref)
    {
       $reserve->{'dateReserve'} = date_text($reserve->{'dateReserve'}, 0);
       $reserve->{'dateExpiry'} = date_text($reserve->{'dateExpiry'}, 0);
       push @reserveList,$reserve;
    }
    $sth->finish;
   return \@reserveList;
}


#----------------------------------------------------------
sub GetStatusDate
{
    my ($dbh, $bc) = @_;

    my ($dateLost, $dateDamage, $uid);
    
    my $sql = "select ondate, uid from opl_lost as lt, opl_loan as ln where lt.idloan=ln.idloan 
                    and ln.barcode='$bc' and dateReturn is not null order by dateLoan desc";
    my $query = $dbh->prepare($sql);
    $query->execute();
    ($dateLost, $uid) = $query->fetchrow_array;
    $query->finish;

    $sql = "select ondate from opl_damage as d, opl_loan as l where d.idloan=l.idloan
                and l.barcode='$bc' and dateReturn is not null order by dateLoan desc";
    $query = $dbh->prepare($sql);
    $query->execute();
    ($dateDamage) = $query->fetchrow_array;
    $query->finish;

    $sql = "select ondate, status from opl_itemstatus where barcode='$bc' &&  (note is null || note <>'merged') order by id desc";
    $query = $dbh->prepare($sql);
    $query->execute();
    my ($dateStatus, $status) = $query->fetchrow_array;
    $query->finish;

    if ( !$dateLost && !$dateDamage && !$dateStatus ) { 
        $status = ITEM_ACTIVE;
         return ($status, 0, undef, undef,undef); 
     }

    my $circ = 1;
    if ( ($dateLost ge $dateDamage) && ($dateLost ge $dateStatus) ) { $status = ITEM_LOST; }
    elsif ( ($dateDamage ge $dateLost) && ($dateDamage ge $dateStatus) ) { $status = ITEM_DAMAGED; }
    elsif ( ($dateStatus ge $dateLost) && ($dateStatus ge $dateDamage) )
    {
        if ( $status == ITEM_DAMAGED || $status == ITEM_LOST ) 
        { 
            $circ = 0;
        }
    }




    my ($firstname, $lastname);
    if ( ($status == ITEM_LOST || $status == ITEM_DAMAGED) && $circ )
    {
        $query = $dbh->prepare("select firstname, lastname from opl_user where uid=$uid");
        $query->execute();
        ($firstname, $lastname) = $query->fetchrow_array;
        $query->finish;
    }
    return ($status, $circ, $firstname, $lastname,$dateStatus);
}


