#!/usr/bin/perl

#use utf8;
use strict;
use CGI;
use Encode;

use Opals::Context;use POSIX qw(
    ceil
);

use Opals::Template qw(
    tmpl_read
    tmpl_write
    tmpl_preference
);
use Opals::Search qw(
    srch_barcodeUsed
    srch_barcodeLocked
    srch_barcodeDuplicated
    srch_templateMarcRecord
    srch_templateMarcList
    srch_getMarcImport
    srch_getIdenticalRIDs
);
use Opals::MarcXml qw(
    mxml_update
    mxml_saveTemplate
    mxml_deleteTemplate
    mxml_templateMaxOrder
    mxml_isLock
    mxml_newItem
);
use Opals::User qw(
    user_getInformationById
);
use Opals::Utility qw(
    util_getTimeout_min
);
use Opals::Locale qw(
    loc_getMsgFile
    loc_write
);


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

my $cgi = CGI->new;
my $input = $cgi->Vars();
my ($permission, $cookie, $template) = tmpl_read(
        {
            dbh             => $dbh,
            cgi             => $cgi,
            tmplFile        => 'marc21/edit.tmpl',
            reqPermission   => 'marc_edit',
        }
);

my ($zid, $rid, $op, $tmplMarcId, $resultId,$isNewItem);

$zid     = 0;
$rid     = $input->{'rid'};
$op      = $input->{'op'};
$isNewItem = $input->{'isNewItem'};

$tmplMarcId = $input->{'tmplMarcId'};
$resultId   = $input->{'resultId'};
    
 ($rid && $rid =~ m/^[\d]+$/ && $rid >= 0) || ($rid = 0);

my $loginuid = $template->param('curUserId');
my $syspref = tmpl_preference($dbh);
my $self = $ENV{'SCRIPT_NAME'};
my $isIE=($ENV{'HTTP_USER_AGENT'} =~ m/MSIE/)?1:0;
my ($isLock,$last_sessionid,$lockTime);
my $timeout = $syspref->{'timeout'};
# Wed, Jan 14, 2009 @ 14:32:39 EST
my $autoAdd2NewItemList = $syspref->{'autoAdd2NewItemList'};
$autoAdd2NewItemList=0 if ($autoAdd2NewItemList !~ m/^0$|^1$/);
my $timeout_min =  util_getTimeout_min($timeout); # should be from $syspref
my $sessionid = $cgi->cookie('sessionID');

#    Set edit_mode ---- Tue, Oct 21, 2008 @ 13:35:21 EDT
#        edit_mode = 0 : import record 
#        edit_mode = 1 : edit templates
#        edit_mode = 2 : clone record
#        edit_mode = 3 : create new record from template
#        edit_mode = 4 : add holdind(s)
#        edit_mode = 5 : restoreFromArch

if ($permission && $permission->{'marc_edit'}) {
    $template->param(isIE =>$isIE);
    if ($ENV{'REQUEST_METHOD'} !~ m/post/i) {
        if ($ENV{'REQUEST_URI'} !~ m/\?/) {
            $template->param(
                listTemplate => srch_templateMarcList($dbh),
            );
        }
        else {
            $template->param(
                invalidRequestMethod => 1,
            );
        }
    }
    else {
              # GET LIST OF ITEM TYPE FROM opl_itemType TABLE
                my $itemTypeList = getItemTypeList($dbh);
                $template->param(
                    itemTypeList =>  $itemTypeList,
                );


        #if ($rid && $rid =~ m/^[\d]+$/ && $rid >= 0 && $op !~ m/tmplMarcSave/) 
        if (defined $resultId && $rid == 0) {
            my $jsxmlMarc = srch_getMarcImport(
                $dbh, $template->param('curUserId'), $resultId
            );
            #$jsxmlMarc = decode('utf8', $jsxmlMarc);
            my @recDuplicate      = GetRecDuplicate($dbh, $jsxmlMarc, $rid, $resultId);
            $jsxmlMarc =jsXmlEscape($jsxmlMarc );
            $jsxmlMarc =~ s/'/&apos;/g;
            $jsxmlMarc =~ s/[\r\n]+/' +\n'/g;
            $template->param(
                marcEdit     => 1,
                jsxmlMarc    => $jsxmlMarc,
                recDuplicate => \@recDuplicate,
            );
#open bbb, ">/tmp/bbb1";
#print bbb $jsxmlMarc;
#close bbb;
        }
        elsif ($op !~ m/^tmpl/) {
            ($isLock,$last_sessionid,$lockTime) =
                mxml_isLock($dbh, $rid, $loginuid);

            if ($isLock ne 'true'){
                #$sql_rec->execute($loginuid,$rid) || return;
                my $barcodeLocked     = ($rid > 0) ? srch_barcodeLocked($dbh, $rid):'';
                my $barcodeDuplicated = '';
                my $barcodeDeletedErr = '';
                my ($marcxml, $barcodeNew, $barcodeDeleted);
            


                $marcxml = $input->{'marcxml'};
                $marcxml =~ s/\x0d//g;
                
                if ($op eq 'save') {
                    $barcodeNew     = $input->{'bcnew'};
                    $barcodeDeleted = $input->{'bcdel'};
                    $barcodeNew =~ s/,$//; #doan
                    $barcodeDuplicated = srch_barcodeDuplicated($dbh, $barcodeNew);
                    foreach my $bc (split /,/, $barcodeDeleted) {
                        $bc = ',' .$bc.',';
                        if ($barcodeLocked =~ m/$bc/) {
                            $barcodeDeletedErr .= $bc . ',';
                        }
                    }

                    if ($barcodeDuplicated eq '' && $barcodeDeletedErr eq '') {
                        my $cloneRecord= $input->{'cloneRecord'};
                        my $newRecFromTmpl= $input->{'newRecFromTmpl'};
                        my $to_zimport = !($rid || $cloneRecord || $newRecFromTmpl);
                        
                        $rid = mxml_update(
                            $dbh, $rid, $marcxml, $barcodeNew, $barcodeDeleted);
                        # Wed, Jan 14, 2009 @ 15:06:21 EST
                        if($isNewItem eq '1'){
                            mxml_newItem($dbh, $rid);
                        }
                        $template->param(
                            success => $rid,
                            to_zimport => ($to_zimport && $rid),
                        );
                    }
                }
                
                my $jsxmlMarc="";
                my $archId = $input->{'archId'};
                if($op eq 'clone'){
                    $jsxmlMarc = cloneRecord($dbh,$rid);
                    $rid=0;
                    $barcodeLocked="";
                    $template->param(edit_mode=>2,);
                }
                elsif($op eq 'restoreFromArch' && $archId>0){
                    #   Mon, Mar 21, 2011 @ 09:26:15 EDT
                    #   Restored record 
                    my $rOpt = $input->{'rOpt'};
                    $template->param(edit_mode=>5);
                    ($jsxmlMarc,$rid) = getXmlRecordFromArchive($dbh,$archId,$rOpt);
                    $jsxmlMarc = loadRecord($dbh, 0, $jsxmlMarc );

                }
                else{
                    $template->param(edit_mode=>4,);
                    $jsxmlMarc = loadRecord($dbh, $rid, $marcxml, $barcodeDeletedErr);

                }

                $jsxmlMarc =jsXmlEscape($jsxmlMarc );
                # set lock for the record in table  opl_marcRecord
                if ($last_sessionid
                 && $last_sessionid ne $sessionid
                 && $lockTime eq 'true') {
                    # check case same uid but different sessionid
                    # and record is lock or not 
                    $template->param(
                        diffSession  => 1,
                    );
                }
                else {
                    setRecordLock(
                        $dbh, $loginuid, $rid, $timeout_min, $sessionid
                    );
                }

                my $xmlCheck = $jsxmlMarc;
                $xmlCheck =~ s/' \+\n'/\n/g;
                my @ridDuplicate = GetRecDuplicate($dbh, $xmlCheck, $rid, $resultId);
                if (scalar(@ridDuplicate) > 1) {
                    $template->param(
                        recDuplicate => \@ridDuplicate,
                    );
                }

                my $barcodeUsed = ($rid > 0) ? srch_barcodeUsed($dbh, $rid):'';
                $template->param(
                    marcEdit            => 1,
                    jsxmlMarc           => $jsxmlMarc,
                    barcodeUsed         => uc($barcodeUsed),
                    barcodeLocked       => uc($barcodeLocked),
                    barcodeDuplicated   => uc($barcodeDuplicated),
                    barcodeDeletedErr   => uc($barcodeDeletedErr),
                );
            }#if ($isLock ne 'true')
            else{
                my $editor_id = editor($dbh, $rid);
                my ($userInfo, $guardian) = user_getInformationById($dbh,$editor_id); 
                if ($editor_id eq $loginuid){
                    $template->param(sameper => 1 ,);
               }
                $template->param(
                    recLock  => 1,
                    who     => $userInfo->{'firstname'}. ' ' .$userInfo->{'lastname'},
                    where   =>'MARC Editor',       
                );

            }
        }
        else {
            if ($op =~ m/tmplMarcSave/i) {
                mxml_saveTemplate(
                    {
                        dbh     => $dbh,
                        op      => $op,
                        tid     => $tmplMarcId,
                        rank    => $input->{'tmplRank'},
                        name    => $input->{'tmplName'},
                        content => $input->{'marcxml'},
                    }
                );
                
                $template->param(
                    tmplMarcSave    => (($op eq 'tmplMarcSave')?1:0),
                    tmplMarcSaveAs  => (($op eq 'tmplMarcSaveAs')?1:0),
                    tmplName        => $input->{'tmplName'},
                );
            }
            elsif ($op eq 'tmplDelete' && $tmplMarcId) {
                my $tmplName = mxml_deleteTemplate($dbh, $tmplMarcId);
                $template->param(
                    tmplMarcDelete  => 1,
                    tmplName        => $tmplName,
                );
            }
            elsif ($tmplMarcId) {
                my $tmplMarcRec = srch_templateMarcRecord($dbh, $tmplMarcId);
                my $jsxmlMarc = $tmplMarcRec->{'content'};
                $jsxmlMarc =jsXmlEscape($jsxmlMarc );
                $jsxmlMarc =~ s/'/&apos;/g;
                $jsxmlMarc =~ s/[\r\n]+/' +\n'/g;
                my $maxTemplateOrder =mxml_templateMaxOrder($dbh) +1;
                $template->param(
                    marcEdit    => 1,
                    edit_mode    => ($op eq 'tmplEdit')? 1:3,
                    tmplMarcId  => $tmplMarcId,
                    tmplRank    => $tmplMarcRec->{'rank'},
                    tmplName    => $tmplMarcRec->{'name'},
                    jsxmlMarc   => $jsxmlMarc,
                    maxOrder    => $maxTemplateOrder,
                );
            }
            
            if ($op !~ m/^(tmplNewRec|tmplEdit)$/) {
                $template->param(
                    listTemplate => srch_templateMarcList($dbh),
                );
            }
        }#else 
    }#if ($permission && $permission->{'marc_edit'}

    $template->param(
        rid => $rid,
        resultId => $resultId,
        autoAdd2NewItemList =>$autoAdd2NewItemList,
    );
}
else {
    my @form_input;
    foreach my $param (keys %{$input}) {
        push @form_input, {name =>"$param",value => "$input->{$param}"};
    }
    $template->param(
        input=>\@form_input,
    );
}

$template->param(hlpUrl     => Opals::Constant->getHlpUrl('marc_edit') );
$template->param(curLang=>$ENV{'curLang'});
  my $msgValMap={
                    marc21Edit_msg03=>{rid=>$template->param('rid')},
                    marc21Edit_msg04=>{tmplName=>$template->param('tmplName')},
                    marc21Edit_msg05=>{tmplName=>$template->param('tmplName')},
                    marc21Edit_msg06=>{tmplName=>$template->param('tmplName')}
                    };
  my $marc21EditMsgMap =loc_getMsgFile('marc21/edit.msg',$msgValMap);
  loc_write($template,$marc21EditMsgMap);

tmpl_write($dbh, $cgi, $cookie, $template);
#$dbh->disconnect();
##############################################################################
sub editor {
    my ($dbh, $rid) = @_;
    my $retval = '';
    my $sql_MARCrec = $dbh->prepare(<<_SQL_);
select  editUid,sessionid, time_to_sec(timediff(lockExpire, now())) as deltaLockTime
from    opl_marcRecord
where   rid = ?
_SQL_
    $sql_MARCrec->execute($rid);
    my $sf = $sql_MARCrec->fetchrow_hashref;
    if ($sf->{'deltaLockTime'} > 0) {
        $retval = $sf->{'editUid'};
    }
    $sql_MARCrec->finish;
    return $retval; 
}
##############################################################################
=item
sub isLock {
    my ($dbh, $rid) = @_;
    my $retval = 'false';
    my $sql_MARCrec = $dbh->prepare(<<_SQL_);
select  recLock, time_to_sec(timediff(lockExpire, now())) as deltaLockTime
from    opl_marcRecord
where   rid = ?
_SQL_
    $sql_MARCrec->execute($rid);
    my $sf = $sql_MARCrec->fetchrow_hashref;
    if ($sf->{'recLock'} eq 'true' || $sf->{'deltaLockTime'} > 0) {
        $retval = 'true';
    }
    $sql_MARCrec->finish;
    return $retval; 
}
=cut
###############################################################################
sub setRecordLock {
    my ($dbh, $loginuid, $rid, $timeout_min, $sessionID) = @_;
    my $sql_rec = $dbh->prepare(<<_SQL_);
update  opl_marcRecord
set     sessionid = ?,
        lockExpire = now() + interval ? MINUTE,
        editUid = ?
where   rid = ?
_SQL_

    $sql_rec->execute($sessionID, $timeout_min, $loginuid, $rid) || return;
    $sql_rec->finish;
}
################################################################################

sub loadRecord {
    my ($dbh, $rid, $marcxml, $barcodeDeletedErr) = @_;

    my $jsxmlMarc;
    if ($rid == 0) {
        $jsxmlMarc = $marcxml;
    }
    else {
        $jsxmlMarc .=getXmlRecord($dbh, $rid);
     
        if ($barcodeDeletedErr ne '') {
            my $xml = $jsxmlMarc;
            my $xmlHolding = '';
            while ($xml =~ s/([\s]*<datafield tag="852" ind1="[\d ]" ind2="[\d ]">\n([\s]*<subfield code="[\w\d]">.*<\/subfield>\n)*[\s]*<\/datafield>\n)//) {
                my $f852 = $1;
                foreach my $bcode (split(/,/, $barcodeDeletedErr)) {
                    if ($f852 =~ m/<subfield code="p">$bcode<\/subfield>/) {
                        $xmlHolding .= $f852;
                    }
                }
            }
#open mxml, ">/tmp/mxml";
#print mxml "<record>$xmlHolding</record>";
#close mxml;
            # Add back outstanding holding
            $jsxmlMarc =~ s/<\/record>/$xmlHolding<\/record>/;
        }
    }

    $jsxmlMarc =~ s/'/&apos;/g;
    $jsxmlMarc =~ s/\n/' +\n'/g;

    return $jsxmlMarc;
}

################################################################################
sub getXmlRecord{
    my ($dbh, $rid) = @_;
    my $xmlMarc="";
    my $config = Opals::Context->config();

    my $zRoot       = Opals::Context->config('zRoot');
    my $zPort       = Opals::Context->config('zPort');
    my $zDatabase   = Opals::Context->config('zDatabase');
    my $path = "$zRoot/$zPort/record/$zDatabase/"
             . ceil($rid/1000) . '/'
             . $rid . '.xml';

    open RECORD, "<$path";
    my $line;
    while (<RECORD>) {
        $line = $_;
        if ($line =~ m/<subfield code="-">/) {
            next;
        }
        
        $xmlMarc .= $line;
    }
    close RECORD;
    return  $xmlMarc;   
}
################################################################################
sub cloneRecord{
    my ($dbh, $rid) = @_;
    my $xmlMarc =getXmlRecord($dbh, $rid);
    my $tmpf852 = "";
    $xmlMarc =~ s/<controlfield tag="001">.*<\/controlfield>/<controlfield tag="001">0<\/controlfield>/gi;    
    while ($xmlMarc =~ s/([\s]*<datafield tag="852" ind1="[\d ]" ind2="[\d ]">\n([\s]*<subfield code="[\w\d]">.*<\/subfield>\n)*[\s]*<\/datafield>\n)//) {
        if($tmpf852 eq ''){
            $tmpf852 =$1;
        }    
    }
    $tmpf852 =~ s/<subfield code="p">.*<\/subfield>/<subfield code="p"><\/subfield>/gi; 
    $xmlMarc =~ s/<\/record>/$tmpf852<\/record>/;
    $xmlMarc =~ s/'/&apos;/g;
    $xmlMarc =~ s/\n/' +\n'/g;

    return $xmlMarc;
}

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

sub GetRecDuplicate {
    my ($dbh, $jsxmlMarc, $rid, $resultId) = @_;

    my @recDuplicate;

    if (defined $resultId) {
        push @recDuplicate, {
            recId => "new",
            newRec => 1,
        };
    }

    $jsxmlMarc =~ s/' \+\n'/\n/g;

    my $marc = Opals::Marc::Record::newFromXml($jsxmlMarc);
    my $ridGroups = srch_getIdenticalRIDs($dbh, $marc);

    my $ridList;
    foreach my $id (@Opals::Search::RECORD_IDENTIFIERS) {
        my $sf = $id->{'tag'} . $id->{'code'};

        foreach my $row (@{$ridGroups->{$sf}}) {
            $ridList->{$row->{'rid'}} = 1;
        }
    }

    if (scalar(keys %{$ridList}) == 0) {
        return;
    }

    foreach my $rec_id (sort keys %{$ridList}) {
        push @recDuplicate, {
            recId => $rec_id,
            sel   => ($rid && $rid == $rec_id) ? 1 : 0,
        };
    }

    return @recDuplicate;
}
################################################################################
sub getXmlRecordFromArchive{
    my ($dbh,$archid,$resOpt) = @_;
    my ($rid,$xmlMarc) = $dbh->selectrow_array(<<_SQL_);
    select rid,UNCOMPRESS(marcXml) as marcXml 
    from  opl_recordArchive 
    where archId = $archid
_SQL_
    
    $xmlMarc =~ s/[\s]*<subfield code="-">.*<\/subfield>//g;

    if($resOpt eq 'merge'){       
        # From current marc record
        my $xml = getXmlRecord($dbh,$rid);

        # From archive Table
        my $barcode;
        my $newSubFields="";
        while ($xmlMarc =~ s/([\s]*<datafield tag="852" ind1="[\d ]" ind2="[\d ]">([\s]*<subfield code="[\w\-]">.*<\/subfield>)*[\s]*<\/datafield>)//) {
            my $f852 = $1;
            if ($f852 =~ m/<subfield code="p">(.*)<\/subfield>/i) {
                $barcode =$1;
                $newSubFields .= $f852; 
                while ($xml =~ s/([\s]*<datafield tag="852" ind1="[\d ]" ind2="[\d ]">([\s]*<subfield code="[\w\-]">.*<\/subfield>)*[\s]*<\/datafield>)//) {
                    my $tmp852 = $1;
                    if ($tmp852 !~ m/<subfield code="p">$barcode<\/subfield>/ ){
                        $newSubFields .= $tmp852 ;
                    }
                }
                
            }
        }
        $xmlMarc =~ s/[\s]*<\/record>/$newSubFields\n<\/record>/;
    } #END if($resOpt eq 'merge')

    return  ($xmlMarc,$rid);   
}
################################################################################
sub jsXmlEscape{
    my ($xml)=@_;
    my $backwardslash ="___OPALS_MARC_XML_backwardslashmarker_f801d6faada54a60faa577bbb60f33___";
    my $forwardslash  ="___OPALS_MARC_XML_forwardslashmarker_f801d6faada54a60faa577bbb60f33___";
    while($xml =~ m/<subfield code="[\w]">.*\/.*<\/subfield>/){
        $xml =~ s/(<subfield code="[\w]">)(.*)\/(.*)(<\/subfield>)/$1$2$forwardslash$3$4/g;
    }
    while($xml =~ m/<subfield code="[\w]">.*\\.*<\/subfield>/){
        $xml =~ s/(<subfield code="[\w]">)(.*)\\(.*)(<\/subfield>)/$1$2$backwardslash$3$4/g;
    }
    $xml =~ s/$forwardslash/\\\//g;
    $xml =~ s/$backwardslash/\\\//g;
 
   
    return $xml;
}
################################################################################
sub updatePreference {
    my ($dbh,$uid,$applName) = @_;
    my $preference;
    my $val = $uid .','. $applName;
    my $sth = $dbh->prepare(<<_STH_);
update opl_preference 
   set val= '$val'
where var = 'recordLock';
_STH_
    $sth->execute() ;
    $sth->finish;
}

################################################################################     
### Add 2008 02 14 : Item type Authority
sub getItemTypeList{
    my ($dbh)= @_;
    my $sql = <<_SQL_;
SELECT     distinct id 
FROM       opl_itemType
ORDER BY    id
_SQL_

    my $sth = $dbh->prepare($sql);
    $sth->execute();
    my @retVal;
    my $itentypeStr=""; 
    while (my $id = $sth->fetchrow_hashref) {
          push @retVal, $id;
    }
    $sth->finish;
           
    return \@retVal;
}

