#!/usr/bin/perl
use strict;
use Date::Parse;
use Time::Local;
use POSIX qw(
    strftime
    ceil
);
use MARC::Record;
use MARC::Field;
use MARC::File::XML;
use Opals::Marc::Record;
my $scriptname;

BEGIN {
    $scriptname = `basename $0`;
    chomp $scriptname;

    sub print_help {
    print <<_STR_;
NAME:
    $scriptname: generic cron script for OPALS sites.
SYNOPSIS:
    PERL5LIB=/www/\$VERSION/module OPALS_CONF=/etc/opals/conf/\$SITECODE $0
_STR_
    }

    if (!$ENV{'PERL5LIB'} || !$ENV{'OPALS_CONF'}) {
        print_help();
        exit 1;
    }
}

use strict;
use Text::CSV_XS;

use Opals::Context;

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

my ($ARL)=$dbh->selectrow_array("select val from opl_preference where var='showARL'");

exit 0 if(!defined $ARL || $ARL eq '0');

my $zRoot   = Opals::Context->config('zRoot');
my $zPort   = Opals::Context->config('zPort');
my $zDatabase = Opals::Context->config('zDatabase');

my $lexileFile="/data/opals/lexile/lexile.csv";
my $lastUpdate=$ENV{'FROM_DATE'};
$lastUpdate="" if(!defined $lastUpdate || $lastUpdate !~ m/^\d\d\d\d-\d\d-\d\d$/);
my $updated={};
my $lexileTbl=getLexileFromFile($lexileFile);
if(defined $lastUpdate && $lastUpdate =~ m/^\d\d\d\d-\d\d-\d\d$/){
    my $lastUpdate_yw= getYearWeekNo($lastUpdate);
    updateFromLexileTbl($dbh,$lastUpdate_yw);
    updateFromRecord($dbh,$lastUpdate);
}
else{
    updateFromRecord($dbh);
}

exit 0;
#==================================================================================================
sub updateFromLexileTbl{
    my($dbh,$fromYearWeek)=@_;
    my $sth=$dbh->prepare(<<_SQL_);
    select distinct i.rid from opl_item i inner join opl_recordIdentifier r using(rid) 
    where i.barcode not regexp '___' &&  tag='020' && code='a' && data=?
_SQL_

    foreach my $yw(keys %$lexileTbl){
        if($yw gt $fromYearWeek){
            foreach my $isbn13(keys %{$lexileTbl->{$yw}}){
                $sth->execute($isbn13);
                while(my ($rid)=$sth->fetchrow_array){
                    updateMarcLexile($dbh,$rid,$lexileTbl->{$yw}->{$isbn13}->{'code'},$lexileTbl->{$yw}->{$isbn13}->{'lexile'});
                }
            }
        }
    }

}
#==================================================================================================
sub updateFromRecord{
    my($dbh,$fromDate)=@_;
    my $sql=<<_SQL_;
        select distinct i.rid,r.data  from opl_item i inner join opl_recordIdentifier r using(rid) 
        where i.barcode not regexp '___' &&  tag='020' && code='a' 
_SQL_
    if(defined $fromDate && $fromDate=~ m/^\d\d\d\d-\d\d-\d\d$/){
        $sql.= " && i.dateImport >'$fromDate'";
    }
    my $sth=$dbh->prepare($sql);
    $sth->execute();
    my $lexile=undef;
    while(my ($rid,$isbn13)=$sth->fetchrow_array){
        if($lexile=getLexileByISBN13($isbn13)){
            updateMarcLexile($dbh,$rid,$lexile->{'code'},$lexile->{'lexile'});
        }
    }

}

#==================================================================================================
sub updateMarcLexile{
    my($dbh,$rid,$code,$lexile)=@_;
    return if($updated->{$rid} || ($code eq"" && $lexile eq ""));
    my $dir     = "$zRoot/$zPort/record/$zDatabase/" . ceil($rid/1000);
    my $marc=getRecordByRid($rid);
    return if(!defined $marc);

    $updated->{$rid}=1;
    my $lVal="$code $lexile";
    $lVal=~ s/^ +| +$//g;
    my $lexileField = MARC::Field->new( 521, '8', '0', 'a' => $lVal,'b' => 'Lexile');
 
    my @fields=$marc->field('521');
    my $updated=0;
    my $hasLexile=0;
    foreach my $f(@fields){
        if($f->indicator(1) ==8){
            if($f->subfield('b') =~/lexile/i){
                $hasLexile=1;
                if($f->subfield('a') eq $lVal){
                    $updated=1;
                }
                else{
                    $f->update('a'=>$lVal);
                }
            }
        }
    }
    if(!$hasLexile){
        $marc->insert_fields_ordered($lexileField);
    }
    if(!$updated){
        printf "rid:%s\tcode:%s\tlexile:%s\n",$rid , $code,$lexile;
        $dbh->do("update opl_marcRecord set modDate=now() where rid=?",undef,$rid);
        my $marcXml = MARC::File::XML::record($marc);
        open RECORD, ">$dir/$rid.xml";
        print RECORD $marcXml;
        close RECORD;
    }

}

#===================================================================================
sub getRecordByRid {
    my ($rid) = @_;
    my $xml = '';
    my $dir     = "$zRoot/$zPort/record/$zDatabase/" . ceil($rid/1000);
    if (! -f "$dir/$rid.xml") {
        print "ERROR: $dir/$rid.xml: not found.\n";
        return;
    }
    open RECORD, "<$dir/$rid.xml";
    while (<RECORD>) {
        $xml .= $_; 
    }
    close RECORD;
    my $marc = Opals::Marc::Record::newFromXml($xml);
    return $marc;
}

#===================================================================================

sub getYearWeekNo{
    my ($date)=@_;
    $date="2010-01-01" if(!defined $date || $date !~ m/^\d\d\d\d-\d\d-\d\d/ ); 
    my ($ss,$mm,$hh,$day,$month,$year,$zone) = strptime($date,"%y-%m-%d");
    $year +=1900;
    my $epoch = timelocal($ss,$mm,$hh, $day, $month , $year);
    my $week  = strftime( "%U", localtime( $epoch ) );
    return "$year-$week";

}

#===================================================================================

sub getLexileFromFile{
    my ($file)=@_;
    my $csv = Text::CSV_XS->new({ binary => 1 });
    open LEXILE,"<$file";
    my  $lexileTbl={};
    #skip first line
     (<LEXILE>);
    
    while(<LEXILE>){
        $csv->parse($_);
        my ($yw,$isbn13,$code,$lexile,$modDate)=$csv->fields();
        $lexileTbl->{$yw} ={} if(!$lexileTbl->{$yw});
        $lexileTbl->{$yw}->{$isbn13}={code=>$code,lexile=>$lexile};

    }
    return $lexileTbl;
}
#===================================================================================
sub getLexileByISBN13{
    my ($isbn13)=@_;
    my $lexile=undef;
    foreach my $yw(keys %$lexileTbl){
          if($lexile=$lexileTbl->{$yw}->{$isbn13}){
             last;
          }
    }
    
    return  $lexile;
}
exit 0;
