#!/usr/bin/perl -w

# Instead of using
#use lib '/www/opals/module/';
# use
# PERL5LIB=/www/opals/module OPALS_CONF=/etc/opals/conf/$SITECODE \
#        $SCRIPT_NAME param1 param2 ...
# or
# time for i in /etc/opals/conf/*;do PERL5LIB=/www/opals/module OPALS_CONF=$i /www/opals/script/util/restore_empty_fields -t 201409051530.00 -b /data/20140905/;done;unset i;date

BEGIN {
    sub print_help {
    print <<_STR_;
NAME:
    OPALS tool to restore empty fields or fields having empty subfields.
SYNOPSIS:
    PERL5LIB=/www/opals/module OPALS_CONF=/etc/opals/conf/\$SITECODE \\
        $0 -t DATETIME -b BACKUP_DIR
DESCRIPTION:
    - DATETIME must be formatted as YYYYMMDDHHMM.SS
    - BACKUP_DIR directory holds record/\$SITECODE/...
_STR_
    }

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

use strict;
use MARC::File::XML;

use Opals::Context;
use Opals::Marc::Record;

use Getopt::Std;
my %options = ();
getopts("t:b:",\%options);
my $ts = $options{t};
my $backupBaseDir = $options{b};
#my $configFile = $options{c};
if (   !$ts|| $ts !~ m/[\d]{12}\.[\d]{2}/
    || !$backupBaseDir || ! -d $backupBaseDir
    ) {
    print_help();
    exit 1;
}

#Opals::Context->set();#$configFile, undef);
my $dbh = Opals::Context->dbh();
END {
    if ($dbh) {
        $dbh->disconnect();
    }
}

$| = 1;
# Codes start...
my $tsFile = "/tmp/ts-$ts";
my $zRoot = Opals::Context->config('zRoot');
my $zPort = Opals::Context->config('zPort');
my $zDatabase = Opals::Context->config('zDatabase');

my $recFile = "/tmp/$zDatabase-$ts";
my $dataBaseDir = "$zRoot/$zPort";
$backupBaseDir =~ s/\/*$//;

system("touch -t $ts $tsFile");
system("find $dataBaseDir/record/$zDatabase/ -type f -cnewer $tsFile".
            " -fprint $recFile");

my ($file, $backupFile, $has_empty_fields);
my ($rid);
open FILE, "<$recFile";
while (<FILE>) {
    chomp;
    $file = $_;
    $backupFile = $_;
    $backupFile =~ s|$dataBaseDir|$backupBaseDir|;

    if (-f $backupFile) {
        $has_empty_fields = `grep '/>' $backupFile`;
        if ($has_empty_fields) {
            restore_fields($dbh, $file, $backupFile);
#            last;
        }
    }
}
close FILE;
# Codes end.

exit 0;
################################################################################


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


sub restore_fields {
    my ($dbh, $file, $backupFile) = @_;

    $rid = `basename $backupFile .xml`;
    chomp $rid;
    print "Processing record $rid...\n";

    # read MARC XML from backup
    my $xml = getXML($backupFile);

    # extract empty fields or fields having empty subfields
    $xml =~ s/[\s]*<(\?xml version|\/?record|leader).*$//mg;
    $xml =~ s/[\s]*<controlfield tag="[\d]{3}">.*?<\/controlfield>//mg;
    $xml =~ s/[\s]*<datafield tag="[\d]{3}" ind1="." ind2=".">([\s]*<subfield code=".">.*?<\/subfield>)*[\s]*<\/datafield>//mg;
    $xml =~ s/[\s]*<datafield tag="521" ind1="8" ind2="0">.*?<subfield code="b">Lexile<\/subfield>.*?<\/datafield>//sg;

    # remove empty lines
    $xml =~ s/^[\r\n]*//g;

    # verify holdings
    my $missingHoldings = '';
    my $file_xml = getXML($file);
    while ($xml =~ s/([\s]*<datafield tag="852" ind1="." ind2=".">.*?<\/datafield>)//s) {
        my $h = $1;
        $h =~ m/<subfield code="p">(.*?)<\/subfield>/s;
        my $barcode = $1;

        $h =~ m/<subfield code="\+">(.*?)<\/subfield>/s;
        my $pathcode = $1;

        if (isMissed($dbh, $file_xml, $rid, $pathcode, $barcode) eq 'true') {
            $missingHoldings .= $h;
        }
    }

    $xml .= $missingHoldings;

    return unless $xml;

    $file_xml =~ s/(<\/record>)/$xml\n$1/;

    my $marc = Opals::Marc::Record::newFromXml($file_xml);

    $xml = MARC::File::XML::record($marc);

#    system("cp -v $file $file.bak");
    open REC, ">$file";
    print REC $xml;
    close REC;

    print "Restored record $rid.\n";
}
############################################################


sub getXML {
    my ($file) = @_;

    my $xml = "";
    open MARCXML, "<$file";
    while (<MARCXML>) {
        $xml .= $_;
    }
    close MARCXML;

    if ($xml =~ m/  <\/record>/) {
        $xml =~ s/^  //mg;
    }

    return $xml;
}
############################################################


sub isMissed {
    my ($dbh, $file_xml, $rid, $pathcode, $barcode) = @_;

    return 'false' if $file_xml =~ m/<subfield code="p">$barcode<\/subfield>/;

    my @param = ($barcode);
    my ($c) = $dbh->selectrow_array(<<_SQL_, undef, @param);
select  count(*)
from    opl_item
where   barcode = ?
_SQL_

    return ($c > 0) ? 'true' : 'false';
}
