#!/usr/bin/perl

# Description:
# Removing space and padding zeroes right after the first character X in bar codes.

# Test after script executed, use correct log file as input:
# while read line; do FILE=`echo $line|sed -re 's/^.* in //'`; BC=`echo $line|sed -re "s/^.* by '//" -e "s/' in .*$//"`; grep -i $BC $FILE > /dev/null; if [ "$?" -ne "0" ]; then echo $BC is not in $FILE; fi; done < /tmp/xaaa_xag3.log

use strict;
use DBI;
use Getopt::Std;
use POSIX qw(
    ceil
);

my %options = ();
getopts("c:",\%options);
my $configFile = $options{c};
if (!$configFile || ! -f $configFile) {
    print "Usage: $0 -c CONFIG_FILE\n";
    exit 1;
}

my $config = loadConfig($configFile);
my $dbh = makeConnection($config);
END {
    if ($dbh) {
        $dbh->disconnect();
    }
}

$| = 1;
# Codes start...

rm_spaces_and_padding_zeroes_from_barcode($dbh, $config);

# Codes end.

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


sub makeConnection {
    my ($config) = @_;
    if (!$config) {
        return;
    }
    my ($db_driver, $db_name, $db_host, $db_port, $db_user, $db_password);

    $db_driver   = $config->{'db_driver'} || 'mysql';
    $db_name     = $config->{'db_name'};
    $db_host     = $config->{'db_host'};
    $db_port     = $config->{'db_port'}   || '3306';
    $db_user     = $config->{'db_user'};
    $db_password = $config->{'db_password'};

    my $dsn = "dbi:$db_driver:$db_name:$db_host:$db_port";

    return DBI->connect($dsn, $db_user, $db_password);
}
############################################################


sub loadConfig {
    my ($configFile) = @_;
#    print "Enter the config filename of Opals: ";
#    $configFile = <STDIN>;
    my $config = {};

    open CONF, $configFile || die "Cannot open file $configFile";
    while (<CONF>) {
        chomp;
        s/#.*//;                # remove comments
        next if /^\s*$/;        # ignore blank lines

        if (/^\s*(\w+)\s*=\s*(.*?)\s*$/) {
            $config->{$1} = $2;
        }
    }
    close CONF;

    return $config;
}
############################################################
############################################################


sub rm_spaces_and_padding_zeroes_from_barcode {
    my ($dbh, $conf) = @_;

    my $updateList = getUpdateList($dbh, $conf);
    updateBarcode($dbh, $conf, $updateList);
}
############################################################


sub getUpdateList {
    my ($dbh, $conf) = @_;

    my $sth = $dbh->prepare(<<_SQL_);
select  *
from    opl_item
where   barcode regexp '^x[ 0]+[1-9][0-9]*'
_SQL_

    my $sth_bc = $dbh->prepare(<<_SQL_);
select  count(*)
from    opl_item
where   barcode like ?
_SQL_

    $sth->execute() || return;

    my ($cur_bc, $new_bc, $count);
    my ($updateList, $checkList);
    while (my $i = $sth->fetchrow_hashref) {
        $cur_bc = $i->{'barcode'};

        $new_bc = $cur_bc;
        if ($new_bc =~ s/^x[ 0]+([1-9][\d]*)$/X$1/i) {
            $sth_bc->execute($new_bc);
            ($count) = $sth_bc->fetchrow_array();
            if ($count == 0 && $checkList->{$new_bc} == undef) {
                $checkList->{$new_bc} = 1;
                $updateList->{$i->{'rid'}}->{$cur_bc}->{$new_bc} = 1;
            }
            else {
                print "Conflicting bar code: $new_bc\n";
            }
        }
    }
    $sth->finish;
    $sth_bc->finish;

    return $updateList;
}
############################################################


sub updateBarcode {
    my ($dbh, $conf, $updateList) = @_;

    my $log = '/tmp/'.$conf->{'db_name'}.'.log';

    my ($rec, $holding, $file, $replacement, $isUpdated);
    my @barcode;

    open LOG, ">>$log";
    foreach my $rid (sort keys %{$updateList}) {
        $rec = $updateList->{$rid};
        $file = $conf->{'zRoot'} . '/210/record/'
              . $conf->{'zDatabase'} . '/'
              . ceil($rid/1000) . '/'
              . $rid . '.xml';
#        print "$rid:\n$file\n";

#        foreach my $bc (sort keys %{$rec}) {
#            $holding = $rec->{$bc};
#            print "\t'$bc'\n";
#        
#            @barcode = keys %{$holding};
#            if (scalar(@barcode) == 1) {
#                print "\t\t'",$barcode[0],"' => ", $holding->{$barcode[0]}, "\n";
#            }
#            else {
#                print "There are more than one replacement bar code:\n"
#            }
#        }

        if (-r $file) {
            $isUpdated = 0;

            open FILE, "<$file";
            my $xml = '';
            my $line;
            my $in852 = 0;
            while (<FILE>) {
                $line = $_;
                if ($line =~ m/<datafield tag="852" ind1="/) {
                    $in852 = 1;
                }
                if ($in852 == 1 && $line =~ m/<\/datafield>/) {
                    $in852 = 0;
                }

                if ($in852 == 1 && $line =~ m/<subfield code="p">/) {
                    foreach my $bc (sort keys %{$rec}) {
                        $holding = $rec->{$bc};
            
                        @barcode = keys %{$holding};
                        if (scalar(@barcode) == 1) {
                            $replacement = $barcode[0];
                            if ($line =~ s/<subfield code="p">$bc<\/subfield>/<subfield code="p">$replacement<\/subfield>/i) {
                                print LOG "Replace '$bc' by '$replacement' in $file\n";
                                $isUpdated = 1;
                                updateBarcode_inSqlDb($dbh, $bc, $replacement);
                            }
                        }
                        else {
                            print "There are more than one replacement bar code:\n"
                        }
                    }
                }

                $xml .= $line;
            }
            close FILE;

            #print "$xml\n";

            if ($isUpdated == 1) {
#                $file .= '.new';
                open FILE, ">$file";
                print FILE $xml;
                close FILE;
            }
        }
        else {
            print "$file not found.\n";
        }

    }
    close LOG;
}
############################################################


sub updateBarcode_inSqlDb {
    my ($dbh, $bc, $barcode) = @_;

    foreach my $table qw(found ge852record historyItem hold inventory item itemInfo itemstatus loan sessionVar) {
        #print "Replace '$bc' by '$barcode' in opl_$table\n";
        $dbh->do(<<_SQL_);
update  opl_$table
set     barcode = '$barcode'
where   barcode like '$bc'
_SQL_
    }
}
