package Opals::Template;

use Exporter;
@ISA       = qw(Exporter);
# Symbols to be exported by default
#@EXPORT    = qw(
#    
#);
# Symbols to be exported on request
@EXPORT_OK = qw(
    tmpl_read
    tmpl_pageList
    tmpl_rangedPageList
    tmpl_searchFieldAdvance
    tmpl_searchFieldOrder
    tmpl_write
    tmpl_redirect
    tmpl_preference
    tmpl_OWLSrchFieldOrder
    tmpl_getSearchFieldList
    tmpl_getRecTypeList
);
#    $searchField
#    $sfIndex
# Version number
$VERSION   = 0.01;


#use utf8;
use strict;
use POSIX qw(
    strftime
    ceil
    floor
);
use Opals::UrlRegistry qw(
    ureg_getUrlRegistry
    ureg_getMenu
);

use HTML::Template;
use Opals::Constant; 
#use Opals::Context;
use Opals::User qw(
    user_currentUser
    user_permission
    user_permission_1
    user_StrPermission
    user_StrPermission_1

);
use Opals::Date qw(
    date_now
    date_text
    date_parse
    date_nearestWorkday
);
use Opals::Search qw(
    srch_systemList
);
use Opals::Locale qw(
    loc_getMsgFile
    loc_write
);
use JSON;
my $menuItem=MENU_ITEM;
my $lang='en';
my $self = $ENV{'SCRIPT_NAME'};#(caller(0))[1];
my $http_host= $ENV{'HTTP_HOST'};
###############################################################################
sub tmpl_OWLSrchFieldOrder{
    my ($sfOrderList) = @_;
    
    my $kwImg; my $titleImg; my $authorImg; my $subImg;
    if($lang eq 'fr'){
        $kwImg      ='/theme/opals/image/children/Keyword_fr.png';
        $titleImg   ='/theme/opals/image/children/Title_fr.png';
        $authorImg  ='/theme/opals/image/children/Author_fr.png';
        $subImg     ='/theme/opals/image/children/Subject_fr.png';
    }
    elsif($lang eq 'ar'){
        $kwImg      ='/theme/opals/image/children/Keyword_ar.png';
        $titleImg   ='/theme/opals/image/children/Title_ar.png';
        $authorImg  ='/theme/opals/image/children/Author_ar.png';
        $subImg     ='/theme/opals/image/children/Subject_ar.png';
    }
    elsif($lang eq 'pt'){
        $kwImg      ='/theme/opals/image/children/Keyword_pt.png';
        $titleImg   ='/theme/opals/image/children/Title_pt.png';
        $authorImg  ='/theme/opals/image/children/Author_pt.png';
        $subImg     ='/theme/opals/image/children/Subject_pt.png';
    }
    elsif($lang eq 'es'){
        $kwImg      ='/theme/opals/image/children/Keyword_es.png';
        $titleImg   ='/theme/opals/image/children/Title_es.png';
        $authorImg  ='/theme/opals/image/children/Author_es.png';
        $subImg     ='/theme/opals/image/children/Subject_es.png';
    }
    elsif($lang eq 'en'){
        $kwImg      ='/theme/opals/image/children/Keyword_en.png';
        $titleImg   ='/theme/opals/image/children/Title_en.png';
        $authorImg  ='/theme/opals/image/children/Author_en.png';
        $subImg     ='/theme/opals/image/children/Subject_en.png';
    }
    else{
        $kwImg      ='/theme/opals/image/children/Keyword.png';
        $titleImg   ='/theme/opals/image/children/Title.png';
        $authorImg  ='/theme/opals/image/children/Author.png';
        $subImg     ='/theme/opals/image/children/Subject.png';
     }

    my $searchField = {
        keyword=>{
            attVal  => 1016,
            att1016 => 1,
            img     => $kwImg,
            attName => 'keyword',
            enabled => 1,
            },
        title=>{
            attVal  => 4,
            att4    => 1,
            img     => $titleImg,
            attName => 'title',
            enabled => 1,
        },
        author=>{
            attVal  => 1003,
            att1003 => 1,
            img     => $authorImg,
            attName => 'author',
            enabled => 1,
        },
        subject=>{
            attVal  => 21,
            att21   => 1,
            img     => $subImg,
            attName => 'subject',
            enabled => 1,
        }
   };

    my @OWLSearchField=();
    $sfOrderList= lc $sfOrderList;
    my @fieldList=split(",", $sfOrderList);
    my $i =0;
    foreach my $fname(@fieldList){
        $fname =~ s/\s+//g;
        if(defined $searchField->{$fname}){            
            $searchField->{$fname}->{'index'}= $i;
            push @OWLSearchField, $searchField->{$fname};
            $i++;
        }
    }
    if(scalar(@OWLSearchField)==0){
        push @OWLSearchField, $searchField->{'keyword'};
    }
   return \@OWLSearchField;
}

###############################################################################
sub tmpl_getSearchFieldList{
    my($dbh)=@_;
    my $msgValMap ={};
    my $stdMsgMap  =loc_getMsgFile('search/standard.msg',$msgValMap);
    my @sfList;
    my $pref        = tmpl_preference($dbh);
    my $sfOrderList = $pref->{'useAttOrder'};
    my $nonZ3950Attr={"9016"=>1,"9004"=>1,"9021"=>1,"5006"=>1};
    if ($sfOrderList && $sfOrderList =~ m/^list:/i) {
        $sfOrderList =~ s/^list://i;
    }
    elsif ($sfOrderList && $sfOrderList =~ m/^useAtt/i) {
        $sfOrderList = '4,5006,9004,5,6,7,8,9,12,13,16,21,9021,31,59,63,1003,1016,9016,1018,5000,5001,5002';
    }
    else {
        $sfOrderList = '1016,9016,1003,5000,31,13,7,8,16,9,5001,5002,63,59,1018,12,5,21,9021,4,5006,9004,6';
    }
    $sfOrderList =~ s/[\D]+/,/g;
    $sfOrderList =~ s/,+/,/g;
    $sfOrderList =~ s/(^,|,$)//g;
    my @sfOrder = split(/,/, $sfOrderList);
    for (my $i=0; $i<@sfOrder; $i++) {
       my $isZ3950Attr=$nonZ3950Attr->{@sfOrder[$i]}?0:1;
       push  @sfList,{attVal=>@sfOrder[$i],
                      text=>$stdMsgMap->{"sf_att@sfOrder[$i]"},
                      isZ3950Attr=>$isZ3950Attr  };
    }

    my @advSfList =getAdvanceSF($dbh);
    my @boolList=({boolVal=>'or',  boolTxt=>$stdMsgMap->{'boolOr_txt'}},
                  {boolVal=>'and', boolTxt=>$stdMsgMap->{'boolAnd_txt'}},
                  {boolVal=>'not', boolTxt=>$stdMsgMap->{'boolNot_txt'}});
    my $sOrder=0;
    foreach my $input(@advSfList){
#        if ($sOrder ==0){
#            $input->{'attVal'} = 5000 ;
#            $input->{'default'} = 1;
#        }
        foreach my $b(@boolList){
            my $tmpBool={};
               $tmpBool->{'boolVal'} =$b->{'boolVal'};
               $tmpBool->{'boolTxt'} =$b->{'boolTxt'};
               $tmpBool->{'selected'}='selected' if($tmpBool->{'boolVal'} eq $input->{'bool'});
            push @{$input->{'boolList'}},$tmpBool;
        }
        foreach my $sf(@sfList){
            my $f={attVal=>$sf->{'attVal'},text=>$sf->{'text'} };
            $f->{'selected'}='selected' if($f->{'attVal'} eq $input->{'attVal'}) ;
            push @{$input->{'sf'}},$f;
        }
       $input->{'srchOrder'} = $sOrder++;
    }
    return (\@sfList,\@advSfList);
}
################################################################################
sub getAdvanceSF {
    my ($dbh) = @_;

    
    my @advSfList;

    my $pref        = tmpl_preference($dbh);
    my @input = split(/,/, $pref->{'searchAdv'});
    if (@input % 2 == 0) {
        @input = split(/,/, '4,and,1003,or,21,or,5000');
    }
    for (my $i = 0; $i < @input; $i = $i + 2) {
        # boolean operator
        my $attVal = @input[$i];
        my $booVal = lc(@input[$i-1]) if($i>1);
        push @advSfList, {
            attVal  => $attVal,
            bool    =>$booVal,
        };
    }
    return @advSfList;
}

###############################################################################
sub tmpl_searchFieldOrder {
    my $searchField = [
        {
            attVal  => 1016,
            att1016 => 1,
            display => 'anywhere',
            attName => 'Any',
            enabled => 1,
        },
        {
            attVal  => 4,
            att4    => 1,
            display => 'title',
            attName => 'Title',
            enabled => 1,
        },
        {
            attVal  => 5006,
            att5006 => 1,
            display => 'title begins with',
            attName => 'Title',
            enabled => 1,
        },
        {
            attVal  => 5,
            att5    => 1,
            display => 'series title',
            attName => 'Title-series',
            enabled => 1,
        },
        {
            attVal  => 6,
            att6    => 1,
            display => 'uniform title',
            attName => 'Title_uniform',
            enabled => 1,
        },
        {
            attVal  => 7,
            att7    => 1,
            display => 'ISBN',
            attName => 'Identifier_ISBN',
            enabled => 1,
        },
        {
            attVal  => 8,
            att8    => 1,
            display => 'ISSN',
            attName => 'Identifier_ISSN',
            enabled => 1,
        },
        {
            attVal  => 9,
            att9    => 1,
            display => 'LC control number',
            attName => 'Control_number_LC',
            enabled => 1,
        },
        {
            attVal  => 12,
            att12   => 1,
            display => 'record ID',
            attName => 'Control_number_local',
            enabled => 1,
        },
        {
            attVal  => 13,
            att13   => 1,
            display => 'dewey',
            attName => 'Classification_Dewey',
            enabled => 1,
        },
        {
            attVal  => 16,
            att16   => 1,
            display => 'LC classification',
            attName => 'Classification_LC',
            enabled => 1,
        },
        {
            attVal  => 21,
            att21   => 1,
            display => 'subject',
            attName => 'Subject',
            enabled => 1,
        },
        {
            attVal  => 31,
            att31   => 1,
            display => 'date of publication',
            attName => 'Date_publication',
            enabled => 1,
        },
        {
            attVal  => 59,
            att59   => 1,
            display => 'place of publication',
            attName => 'Name_geographic_place_publication',
            enabled => 1,
        },
        {
            attVal  => 63,
            att63   => 1,
            display => 'note',
            attName => 'Note',
            enabled => 1,
        },
        {
            attVal  => 1003,
            att1003 => 1,
            display => 'author keyword',
            attName => 'Author_name',
            enabled => 1,
        },
        {
            attVal  => 1004,
            att1004 => 1,
            display => 'author (personal)',
            attName => 'Author_name_personal',
            enabled => 1,
        },
        {
            attVal  => 1005,
            att1005 => 1,
            display => 'author (corporate)',
            attName => 'Author_name_corporate',
            enabled => 1,
        },
        {
            attVal  => 1018,
            att1018 => 1,
            display => 'publisher',
            attName => 'Name_publisher',
            enabled => 1,
        },
        {
            attVal  => 5000,
            att5000 => 1,
            display => 'bar code',
            attName => 'Bar_code',
            enabled => 1,
        },
        {
            attVal  => 5002,
            att5002 => 1,
            display => 'medium',
            attName => 'Medium',
            enabled => 1,
        },
        {
            attVal  => 5001,
            att5001 => 1,
            display => 'local call number',
            attName => 'Call_number_local',
            enabled => 1,
        },
       ];
    my $sfIndex;

#Value of 'useAttOrder' should be:
#  - 'useAtt': the list will be in Z39.50 use attribute order
#  - 'list:attVal1,attVal2,attVal3,...': the list will be in user-defined order
#  - anything else: the list will be in default order.
#    1016,1003,1005,1004,5000,31,13,7,8,16,9,5001,5002,63,59,1018,12,5,21,4,6
#sub tmpl_searchFieldOrder {
    my ($sfOrderList) = @_;
    if ($sfOrderList && $sfOrderList =~ m/^list:/i) {
        $sfOrderList =~ s/^list://i;
    }
    elsif ($sfOrderList && $sfOrderList =~ m/^useAtt/i) {
        $sfOrderList = '4,5006,5,6,7,8,9,12,13,16,21,31,59,63,1003,1016,1018,5000,5001,5002';
    }
    else {
        $sfOrderList = '1016,1003,5000,31,13,7,8,16,9,5001,5002,63,59,1018,12,5,21,4,5006,6';
    }
    
#    if ($sfOrderList =~ s/^list://) {
        foreach my $sfo (@$searchField) {
            $sfOrderList =~ s/(^$sfo->{'attVal'},|,$sfo->{'attVal'},|,$sfo->{'attVal'}$)/,/g if (!$sfo->{"att$sfo->{'attVal'}"});
        }

        $sfOrderList =~ s/[\D]+/,/g;
        $sfOrderList =~ s/,+/,/g;
        $sfOrderList =~ s/(^,|,$)//g;
        my @sfOrder = split(/,/, $sfOrderList);
        for (my $i=0; $i<@sfOrder; $i++) {
            $sfIndex->{$sfOrder[$i]} = $i;
        }
        foreach my $sfo (@$searchField) {
            $sfo->{'index'} = $sfIndex->{$sfo->{'attVal'}};
        }
    
        @$searchField = sort { $a->{'index'} <=> $b->{'index'}} @$searchField;
#    }
#    else {
#        if ($sfOrderList =~ m/^useAtt/i) {# sort by Z39.50 use attribute value
#            @$searchField = sort { $a->{'attVal'} <=> $b->{'attVal'}} @$searchField;
#        }
#        #else use OPALS default order
#        for (my $i=0; $i<@$searchField; $i++) {
#            $sfIndex->{$searchField->[$i]->{'attVal'}} = $i;
#        }
#    }

    return ($searchField, $sfIndex);
}


sub tmpl_preference {
    my ($dbh) = @_;
    my $preference;

    my $sth = $dbh->prepare(<<_STH_);
select  var, val
from    opl_preference
_STH_
    $sth->execute() || return;

    while (my ($var, $val) = $sth->fetchrow_array) {
        $preference->{$var} = $val;
    }
    $sth->finish;
    my $cat=$dbh->selectrow_hashref("select catid from opl_category where authenticateBySID='1' limit 1");
    $preference->{'authenticateBySID'}=$cat?1:0;
    return $preference;
}



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

# return value:
# - 0: successful
# - 1: username missing
# - 2: username invalid
# - 3: password invalid
sub tmpl_read {
    my ($in) = @_;
   
    my ($dbh, $cgi, $tmplFile, $reqPermission, $tmplLocalVars, $op);
    $dbh            = $in->{'dbh'};
    $cgi            = $in->{'cgi'};
    $tmplFile       = $in->{'tmplFile'};
    $reqPermission  = $in->{'reqPermission'};
    $tmplLocalVars  = $in->{'tmplLocalVars'};
    $op             = $in->{'op'};

 
    my $sessionid = $cgi->cookie('sessionID');
    
    my @cookieList;

    my ($errCode, $user, $template);
    #my ($errCode, $cookie_session, $user, $template);
    my $permission;
   
    my $rootDir = Opals::Context->config('rootDir');
    my $pref = tmpl_preference($dbh);
    
    #Thu, Aug 23, 2012 @ 11:25:07 EDT
    if($self ne '/bin/home' && $pref->{'OpacLoginRequired'} == 1){
        $reqPermission="required_login";
    }
  
       
    my ($theme, $libcode, $libname, $timeclear,$bibtimeclear,$cssTheme);#, $timeformat);
    my ($fineon);
    $theme         = 'opals';#$pref->{'theme'};

    my $defaultLang=$pref->{'lang'};
    my $supportLang=$pref->{'multilingual'};
    $lang = $cgi->cookie('language');
    
    $defaultLang='en' if(!$defaultLang || $defaultLang !~ m/^en$|^fr$|^es$|^pt$|^ar$|^ru$/gi);
    $lang = $cgi->cookie('language');
    $lang=$defaultLang if($lang !~ m/^en$|^fr$|^es$|^pt$|^ar$|^ru$/gi);

    $ENV{'curLang'}= $lang;
    $libcode       = $pref->{'libcode'};
    $libname       = $pref->{'libname'};
    $timeclear     = $pref->{'timeclear'};
    $bibtimeclear  = $pref->{'bibTimeclear'};
    $cssTheme      = $pref->{'cssTheme'};

    $fineon     = $pref->{'fine'};
    ($libcode) || ($libcode = 'OPALS');
    ($libname) || ($libname = 'Open-Source Automated Library System');
    ($cssTheme)||($cssTheme="");

    #######################################
    # Identify user
    my $ck;
    ($errCode, $ck, $user) = Opals::User::user_currentUser($dbh, $cgi);

    @cookieList = @{$ck} if $ck;
    #($errCode, $cookie_session, $user) = user_currentUser($dbh, $cgi);
    #push @cookieList, $cookie_session;

    undef $reqPermission if ($reqPermission eq 'none');

    #######################################
    # Ask user to login or allow/deny access
    if ($errCode==0) {
 
        #$permission = user_permission($dbh, $user->{'uid'});
        $permission = Opals::User::user_permission_1($dbh, $user->{'uid'});
        my ($allowAccessMyFile)=$dbh->selectrow_array("select  allowAccessMyFile from opl_user u inner join opl_category c on u.categorycode =c.catid where u.uid=?",undef,$user->{'uid'});
        $permission->{"allowAccessMyFile"}=$allowAccessMyFile;
        if($sessionid && $sessionid ne''){
            cancelPendingStatusBc($dbh, $user->{'uid'},$sessionid);
            unlockRecord($dbh, $user->{'uid'},$sessionid );
        }
    }

        

   #Thu, Nov 10, 2011 @ 08:36:48 EST
   $defaultLang;
    my $multilingual=$pref->{'multilingual'};
    if($multilingual ne'' && $multilingual !~ m/$defaultLang/){
        $multilingual ="$defaultLang,$multilingual";
    }
    if($multilingual !~ m/en|fr|es|pt|ar|ru/gi){
        $multilingual='en';
    }
    my $langMsgMap  =loc_getMsgFile('headerFooter.msg');
    my @multilingualCnt = split(/,/, $multilingual); 
    my $multilingualOpt=[];
    if(scalar(@multilingualCnt)>1){
        my $isSel =0;
        foreach my $l(@multilingualCnt){
            $isSel =($lang eq $l)? 1:0;
            push @$multilingualOpt,{lang=>$langMsgMap->{"lang_$l"},code=>$l,isSel=>$isSel};
        }

    }
    my $today = date_now();
    my $curDateTime =$today;
       $curDateTime =~ s/\-/\//g;

    $today =~ s/([\d]{4}-[\d]{2}-[\d]{2}) ([\d:])+/$1/;
    $today = date_text($today, 1);
    my $template =getTemplate($dbh,$user,$tmplFile,$pref,$tmplLocalVars);
    $template->param(langOption    => $multilingualOpt);
    $template->param($pref);
    $template->param(curLang =>$lang, "lang_$lang"=>1);
    my $isLibType= "is". $pref->{"libraryType"};
    $isLibType =~s/-//g;
    $template->param($isLibType =>1);

    setSrchfrmData($dbh,$template,$cgi);
#set default sort attribute and sort order
    my $defaultSortArr=$pref->{'defaultSearchResultSort'};
    if(defined $defaultSortArr && $defaultSortArr ne ''){
        $template->param(defaultSortAttr=>$defaultSortArr);
        $template->param(defaultSortOrder=>1) if($defaultSortArr eq '31');
    }
    if($pref->{'barcodeType'} eq '1'){
        $template->param(follettBarcode=>1);
    }
    elsif($pref->{'barcodeType'} eq '2'){
        $template->param(spectrumBarcode=>1);
    }
     elsif($pref->{'barcodeType'} eq '3'){
        $template->param(leadingZeroBarcode=>1);
    }
    elsif($pref->{'barcodeType'} eq '4'){
        $template->param(sagebrushBarcode=>1);
    }
    my $sf0;    
    if ($self eq '/bin/search/standard' ||
        $self eq '/bin/search/zimport') {
        $sf0 = $cgi->param('sf0');
    }
    ($sf0) || ($sf0 = $cgi->cookie('sf0')) || ($sf0 = 1016);
     push @cookieList, $cgi->cookie(-name => 'sf0', -value => $sf0,);
    
    my $menuJson=to_json(ureg_getMenu($permission,$pref),{pretty=>1});        
    $template->param(menuJson=>$menuJson);
    # script registry :
    my $scriptRegistry=ureg_getUrlRegistry($permission,$pref);
    foreach my $sriptName(keys %$scriptRegistry){
        $template->param($sriptName=>$scriptRegistry->{$sriptName});
    }
    # Define user permission (to build menu entry)
    $template->param($permission);

    # Union/ILL scoping
    $template->param(
        systemList => srch_systemList($dbh),
    );
    
    
    my $help_name = $self;
    $help_name =~ s/((\/[^\/]+)+)[\?]?/$1/;
    $help_name =~ s/^\/bin\///;
    $help_name =~ s/\//_/g;
    my $selfcreateAccount=$pref->{'selfcreateAccount'};
    my $disableLibCat =$pref->{'disableLibCat'}|| 0;
    my $catType = Opals::Context->config('type');
    $ENV{'curUserId'}= $user->{'uid'};
    my $lastUpdate = `readlink $rootDir`;
    $lastUpdate =~ s/^[\w]+-//;
    $template->param(
        lastUpdate   => $lastUpdate,
        typeBranch   => ($catType == 0) ? 1 : 0,
        typeUnion    => ($catType == 1) ? 1 : 0,
        typeIll      => ($catType == 2) ? 1 : 0,
        libMultiple  => ($catType) ? 1 : 0,
        template     => "/theme/$theme",
        today        => $today,
        curDateTime       =>$curDateTime,
        curUserId    => $user->{'uid'},
        curUserName  => $user->{'username'},
        curFirstName => $user->{'firstname'},
        curLastName => $user->{'lasttname'},
        curUserPhone  => $user->{'phone'},
        curUserEmail  => $user->{'email'},
        user_invalid => (($errCode == 2) ? 1 : 0),
        pass_invalid => (($errCode == 3) ? 1 : 0),
        sess_timeout => (($errCode == 4) ? 1 : 0),
        timeclear    => convertTime2milisecond($timeclear),
        help_name    => $help_name,
        bibTimeReset => convertTime2milisecond($bibtimeclear),
        textbook_mod => ($self =~ m/\/bin\/txtbk\//) ? 1 : 0,
        equipment_mod=> ($self =~ m/\/bin\/eqmnt\//) ? 1 : 0,
        isNotLibCat => ($disableLibCat || ($self =~ m/\/bin\/(txtbk|eqmnt)\//)) ? 1: 0, 
        selfcreateAccount=> (($selfcreateAccount == 1) ? 1 : 0),
    );
     
     
    foreach my $p (keys %$permission) {
        $template->param($p=>1);
        if ($p eq 'circ_rsrv_self' ){
            $template->param(
                rsrv_self =>1,
                );
        }
        if ($p eq 'circ_rsrv' || $p eq 'circ_loan' || $p eq 'circ_return' || $p eq 'circ_found' ){
            $template->param(
                circ =>1,
                );
        }
        if($p eq 'marc_edit' || $p eq 'marc_add'){
            $template->param(quickItemEntry=>1);
        }
    }
  #  if ($locked) {
  #      tmpl_write($dbh, $cgi, \@cookieList, $template);
   #     exit;
   # }

    my $headerFooterMsgMap  =loc_getMsgFile('headerFooter.msg');
    loc_write($template,$headerFooterMsgMap);
    
    # Mon, Feb 08, 2010 @ 10:28:40 EST
    # In case: session timeout -- User relogin
    my $msgValMap ={};
    my $msgMap            =loc_getMsgFile('util/login.msg',$msgValMap);
    loc_write($template,$msgMap);
    $msgValMap ={};
    my $stdMsgMap  =loc_getMsgFile('search/standard.msg',$msgValMap);
    loc_write($template,$stdMsgMap);


    return ($permission, \@cookieList, $template);
}
##############################################################################
sub getTemplate {
    my($dbh,$user,$tmplFile,$pref,$tmplLocalVars)=@_;
    my ($warned, $locked, $lockingDate, $lockingTime);
    my $permission ={};
   if ($user) {
        $permission = Opals::User::user_permission_1($dbh, $user->{'uid'});
    }


    my $warningDatetime = $pref->{'warningDatetime'};
    my $lockingDatetime = $pref->{'lockingDatetime'};
    my $now   = date_now();
    $now =~ s/[- :]//g;
    if ($warningDatetime && $lockingDatetime) {
        my $wdt = $warningDatetime;
        $wdt =~ s/[- :]//g;

        my $ldt = $lockingDatetime;
        $ldt =~ s/[- :]//g;
        
        if ($ldt < $now) {
            $locked = 1;
        }
        elsif ($wdt < $now) {
            $warned = 1;
            ($lockingDate, $lockingTime) = split(/ /, $lockingDatetime);

            $lockingDate = date_text($lockingDate, 1);
            my $gmt_tz = `date +'EDT %z'`;
            my @t= split ":",$lockingTime;
            my $pmam=$t[0]<12?"AM":"PM";
            if($t[0]>12){
                $t[0]=$t[0] - 12;
            }
            $lockingTime = sprintf("%0d:%0d %s EST",$t[0],$t[1],$pmam);
            #$lockingTime =~ s/:[\d]{2}$/ $lockingTime/;
        }
    }

    if($locked){
        $tmplFile = 'locked.tmpl';
    }
    elsif(!$user){ #user hasn't logined in && script requires permission
        if(($pref->{'OpacLoginRequired'} == 1 && $self ne '/bin/home') || 
            !checkAccessPerm($permission,$self)){
            $tmplFile = 'login.tmpl';
        }
    }
    elsif(!checkAccessPerm($permission,$self)){ #login but has no access permission
        $tmplFile = 'denied.tmpl';
    }
    my $rootDir = Opals::Context->config('rootDir');
    my  $template = HTML::Template->new(
            filename            => "$tmplFile",
            path                => "$rootDir/htdocs/theme/opals",
            global_vars         => !$tmplLocalVars,
            die_on_bad_params   => 0,
            cache               => 1,
            shared_cache        => 0,
            loop_context_vars   => 1,
        );
     $template->param(
        warned       => $warned,
        lockingDate  => $lockingDate,
        lockingTime  => $lockingTime
     );
      return $template;
    
}
#=======================================================
sub UserHasMenuPermission{
   my ($userPermission,$menuPermStr) =@_;
   return 1 if($menuPermStr eq '');
   my $menuPermssion =Opals::User::user_StrPermission_1($menuPermStr);
   foreach my $perm (keys %$menuPermssion){
        if($userPermission->{$perm}==1){
            return 1;
        }
    }
    return 0;
}

#=======================================================
sub tmpl_pageList {
    my ($count, $curPage, $pSize) = @_;
    my $pCount  = ceil($count/$pSize);

    my @pageList = ();
    for (my $i = 1; $i <= $pCount; $i++) {
        push @pageList, {
            pNum    => $i,
            current => (($i == $curPage) ? 1 : 0)
        };
    }

    return @pageList;
}
#=======================================================
# Thu, Aug 12, 2010 @ 09:51:58 EDT
sub setSrchfrmData{
    my($dbh,$template,$cgi)=@_;
    my $input = $cgi->Vars();
    my $iCount=0;
    my ($sfOrder, $kw, $boolop);
    my $kw0=$input->{"kw0"};
    my $sf0=$input->{"sf0"};

    my ($sfList,$inputSearch)=tmpl_getSearchFieldList($dbh);
    my $sf0Index=0;
    foreach my $cgiInput (keys %$input) {
        $iCount++ if ($cgiInput =~ m/^sf[\d]+/);
    }  
    my $j=0;
    my $searchFormVal =[];
    for (my $i = 0; $i < $iCount; $i++) {
        $sfOrder= 'sf' . $i;
        $kw     = 'kw' . $i;
        $boolop = 'boolop' . $i;
        last if(!defined $input->{$kw});

        if($input->{$kw} ne''){
            if($j==0){
                $kw0=$input->{$kw};
                $sf0=$input->{$sfOrder};
            }
            push @$searchFormVal,{inputName=>"kw$j" ,inputVal=> $input->{$kw}};
            push @$searchFormVal,{inputName=>"sf$j" ,inputVal=> $input->{$sfOrder}};
            push @$searchFormVal,{inputName=>"boolop$j" ,inputVal=> $input->{$boolop}};
            $j++;
        }
    }
# record type filter    
    my @recType     = $cgi->param('recType');
    for (my $i =0; $i <scalar(@recType);$i++){
        $template->param("recType_@recType[$i]"=>1);
    }

    $template->param(    
                     searchFormVal=>$searchFormVal,
                     sfList      => $sfList,
                     inputSearch => $inputSearch,
                     kw0         => $kw0,
                     sf0         => $sf0,
                     iCount      => scalar(@$inputSearch),
                    );
    
# Record Type 
    my  $recordTypeArr=  tmpl_getRecTypeList();
    $template->param( recordTypeArr => $recordTypeArr);
# locations
    my $pref        = tmpl_preference($dbh);
    if($pref->{'showLocationFilter'} eq '1'){
        my $locationList = getLocationList($dbh,$input->{'location'});
        if(scalar(@$locationList)>=1){
            $template->param(  locationList=>$locationList);
        }    
    }
}
#=======================================================
sub getLocationList{
    my($dbh,$curSrchLoc)=@_;
    my $locList=[];
    my $sth=$dbh->prepare("select distinct trim(sfData) from opl_authCtrl where sfCode='c' order by sfData");
    $sth->execute();
    while(my  ($location) =$sth->fetchrow_array){
        my $selected=($curSrchLoc eq $location);
        push @$locList,{location=>$location,selected=>$selected};
    }
    return $locList;
}
#=======================================================
# Thu, Nov 15, 2012 @ 14:43:26 EST
# This function to create Advance search option: material type
#     Fill recrord types into 5 columns ...
#
sub tmpl_getRecTypeList{
    my($cols) =@_;
    $cols =($cols||5);


    my  @mediaTypeTbl = ();
    my $recType =RECTYPE_DEF_TBL;
    my $stdMsgMap  =loc_getMsgFile('search/standard.msg');

    while(my ($key, $value) = each(%$recType)){
        next if($key =~  m/^_/) ;
        my $grp=$value->{'group'}->{'order'} . $value->{'group'}->{'subOrder'} ;
        push @mediaTypeTbl,{mType=>$key,grp=>$grp };

    }

    @mediaTypeTbl = sort{ $a->{'grp'} cmp $b->{'grp'}}  @mediaTypeTbl; 
    my $rows= ceil(scalar(@mediaTypeTbl)/$cols);
    my $i=0;
    my $j=0;
    my @arr=();
    foreach my $r( @mediaTypeTbl){
        $i=0 if($i==$rows);
        push @{$arr[$i]->{"item"}} , {mType =>$r->{'mType'}, mTypeLbl=> $stdMsgMap->{$r->{'mType'}}};
        $i++;
    }
    return \@arr;
}
#=======================================================
sub tmpl_rangedPageList {
    my ($count, $curPage, $pSize, $pRange) = @_;
    my $pCount  = ceil($count/$pSize);

    my @rangedPageList = ();
    return  @rangedPageList if($pCount <=1);
    my $msgMap            =loc_getMsgFile('pageNav.msg');
    push @rangedPageList, {
        pFirst   => 1,
        pNum     => 1,
        disabled => (($curPage ==1) ? 1 : 0),
        pName=>$msgMap->{'pageNav_first'}
    };
    push @rangedPageList, {
        pPrevious=> 1,
        pNum     => ($curPage-1),
        disabled     => (($curPage == 1) ? 1 : 0),
        pName=>$msgMap->{'pageNav_previous'}
    };
    
    
#    my $prev_nPage = $curPage - $pRange;
#    ($prev_nPage >= 1) || ($prev_nPage = 1);
#    push @rangedPageList, {
#        pName   => "&lt;&lt;",
#        pNum    => $prev_nPage,
#        disabled => (($curPage <= $pRange) ? 1 : 0),
#    };
    
#    my $startPage = floor(($curPage - 1)/$pRange)*$pRange + 1;
    my $startPage = $curPage - $pRange;
    ($startPage > 0) || ($startPage = 1);
    my $pLimit = $startPage + 2*$pRange;

    #for (my $i = $startPage; $i < $pLimit && $i <= $pCount; $i++) {
    for (my $i = $startPage; $i <= $pLimit; $i++) {
        if ($i <= $pCount) {
            push @rangedPageList, {
                pName => $i,
                pNum  => $i,
                pCur  => (($curPage == $i) ? 1 : 0),
            };
        }
=item        
        else {
            push @rangedPageList, {
                pName => $i,
                pNum  => $i,
                disabled => 1,
            };
        }
=cut        
    }
    
#    my $next_nPage = $curPage + $pRange;
#    ($next_nPage <= $pCount) || ($next_nPage = $pCount);
#    push @rangedPageList, {
#        pName   => "&gt;&gt;",
#        pNum    => $next_nPage,
#        disabled => (($curPage >= floor($pCount/$pRange)*$pRange) ? 1 : 0),
#    };
    push @rangedPageList, {
        pNext    => 1,
        pNum     => ($curPage + 1),
        disabled    => (($curPage == $pCount ) ? 1 : 0),
        pName=>$msgMap->{'pageNav_next'}
    };
    
    push @rangedPageList, {
        pLast    => 1,
        pNum     => $pCount,
        disabled => (($curPage >= $pCount) ? 1 : 0),
        pName=>$msgMap->{'pageNav_last'}
    };

    return @rangedPageList;
}


########################################################################
sub tmpl_searchFieldAdvance {
    my ($dbh) = @_;
    my $searchConfig;

    my $pref = tmpl_preference($dbh);
    
    my @inputSearch;

    my @input = split(/,/, $pref->{'searchAdv'});
    if (@input % 2 == 0) {
        @input = split(/,/, '4,and,1003,or,21,or,5');
    }

    my @boolOp = ('or', 'and', 'not');
    for (my $i = 0; $i < @input; $i = $i + 2) {
        # boolean operator
        my @iBool;
        my $srchOrder = $i/2;
        if ($srchOrder > 0) {
            if ($input[$i-1] !~ m/^or$|^and$|^not$/i) {
                $input[$i-1] = 'or';
            }
            for (my $j = 0; $j < @boolOp; $j++) {
                push @iBool, {
                    iValue      => $boolOp[$j],
                    "is_$boolOp[$j]_lbl" =>1,
                    iChecked    => ( ($boolOp[$j] eq $input[$i-1]) ? 1:0 ),
                };
            }
#            $iBool[0]->{'iChecked'} = 1 if ($input[$i-1] >= @boolOp);
        }
        
        my ($searchField, $sfIndex) = tmpl_searchFieldOrder($pref->{'useAttOrder'});
        push @inputSearch, {
            sfIndex     => $sfIndex->{$input[$i]},
            srchOrder   => "$srchOrder",
            iBool       => \@iBool,
        };
    }

    return @inputSearch;
}

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

sub tmpl_write {
    my ($dbh, $cgi, $cookie, $template, $mime_type) = @_;
    my $i=0;
    # Set system preferences
    my $pref = tmpl_preference($dbh);
    my $colorTheme = $cgi->cookie('colorTheme');
    my $fontTheme = $cgi->cookie('fontTheme');
    $pref->{'colorTheme'} = $colorTheme if($colorTheme ne '');
    $pref->{'fontTheme'}  =  $fontTheme  if($fontTheme ne '');
    $template->param($pref);
    $template->param(prefJson=>to_json($pref));
    
   #Thu, Aug 16, 2007 @ 10:25:35 EDT
   # get weekday closed
   
    my @weekdayClosed;
    my $sth = $dbh->prepare(<<_STH_);
    select weekday 
    from  opl_openHours 
    where (open='' || open regexp 'close')  
_STH_
    $sth->execute;
    while (my $d = $sth->fetchrow_hashref) {
       push  @weekdayClosed,$d;                  
    }
    $sth->finish;

    # Set closing dates

    my @dateClosed;
    $sth = $dbh->prepare(<<_STH_);
select  *
from    opl_dateClosed
order by dClosed asc
_STH_
    $sth->execute;
    while (my $dClosed = $sth->fetchrow_hashref) {
        $dClosed->{'dClosedText'} = date_text($dClosed->{'dClosed'});
        $dClosed->{'pos'}=$i++;
        push @dateClosed, $dClosed;
    }
    $sth->finish;

    my $dateFirst = date_parse($pref->{'dateFirst'});
    my $dateLast  = date_parse($pref->{'dateLast'});
    my $nwd = date_nearestWorkday($dateFirst, $dateLast);
    my ($year, $month, $day) = $nwd->date();
    ($month > 9) || ($month = "0$month");
    ($day > 9) || ($day = "0$day");
    $template->param(
        weekdayClosed => \@weekdayClosed,
        dateClosed => \@dateClosed,
        nearestWorkday => "$year-$month-$day",
    );

    # Tab for external databases
    my $scriptName = $ENV{'SCRIPT_NAME'};
    my @extDatabase;
    $sth = $dbh->prepare(<<_STH_);
select  *
from    opl_extDatabase
where page='searchPage'
order by rank, name, id asc
_STH_
    $sth->execute;
    while (my $es = $sth->fetchrow_hashref) {
        $es->{'VRC'}=1 if($es->{'name'} eq 'VRC');
        $es->{'active'}=1 if($scriptName =~ m/\/vrc$/);
        push @extDatabase, $es;
    }
    $sth->finish;

    $template->param(
        extDatabase => \@extDatabase,
        scriptName=>$scriptName,
        http_host=>   $http_host  ,
    );
    # visitor counter
    my $hitCounter = getVisitorCount($dbh,$cgi,$pref);
    my $hitCounterTxt = sprintf("%09d",$hitCounter);
    push @$cookie, $cgi->cookie(-name => 'hitCounter', -value => $hitCounterTxt,);
    # /visitor counter
    # Output
    $mime_type = 'text/html' unless $mime_type;
    print $cgi->header(
        -type    => $mime_type,
        -expires => 'now',
        -cookie  => ($cookie)?$cookie:'',
        -charset => 'utf-8',
        -FRAME-OPTIONS=> "SAMEORIGIN",
    ),  $template->output;
}

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

sub tmpl_redirect {
    my ($cgi, $script) = @_;

    print $cgi->redirect($script);
}
########################################################################
sub convertTime2milisecond{
    my ($time)=@_;
   if ($time =~ m/(\d+)([smh])/) {
        if (defined $2) {
            my ($num, $unit) = ($1, $2);
            if (!$num || $num eq '') {
                $num = 0;
            }
            if ($2 eq 'm') {
                $num *= 60;
            }
            if ($2 eq 'h') {
                $num *= 3600;
            }
            $time = $num . "000";
        }
        else {
            $time = "300000"; #5m
        }
    }
    else {
        $time = "300000"; #5m
    }
    return $time;
}

########################################################################
sub unlockRecord {
    my ($dbh, $uid,$sessionid ) = @_;
    my $sql_MARCrec = $dbh->prepare(<<_SQL_);
update  opl_marcRecord
set     lockExpire = null
where   editUid = ? &&
        sessionid =?
_SQL_
    $sql_MARCrec->execute($uid,$sessionid);
    $sql_MARCrec->finish;

}


########################################################################
sub cancelPendingStatusBc{
    my ($dbh, $uid,$sessionid ) = @_;
    my $sql_update = $dbh->prepare(<<_SQL_);
update  opl_bcmBc 
set     status = 'available',
        pending = -1, pendingFor ='',
        sessionid = NULL 
where   sessionid = ? && pending = ? && pendingFor ='edit'
_SQL_

    my $sql = $dbh->prepare(<<_SQL_);
select rid from  opl_marcRecord
where   editUid = ? &&
        sessionid =? && 
        (lockExpire is not null || lockExpire  !='')
_SQL_
    $sql->execute($uid,$sessionid);
    my $bcStatus = '';
    while(my ($rid) = $sql->fetchrow_array){
        $sql_update->execute($sessionid,$rid);
    }

    #CASE: clone, zimport
    my $rid =0;
    $sql_update->execute($sessionid,$rid);

    $sql_update->finish;
    $sql->finish;
}
########################################################################
sub getVisitorCount{
    my($dbh,$cgi,$pref)=@_;
    my $counted= $cgi->cookie('hitCounter');
    if(!defined $pref->{'hitCounter'}){
        $dbh->do("insert into opl_preference set val =1,var='hitCounter',hidden=1");
    }
    unless($counted){
        $dbh->do("update opl_preference set val =cast(val as unsigned) +1  where var='hitCounter'");
    }
    my($counter) = $dbh->selectrow_array("select cast(val as unsigned) from opl_preference where var='hitCounter'");
    return $counter;
}


########################################################################
sub checkAccessPerm{
    my($userPerm,$script)=@_;

    my $allowAccess=0;
    $script =~ s/\?.*$//g;
    $script =~ s/\/+/\//g;
    my $scriptRegistry=ureg_getUrlRegistry($userPerm);
    foreach my $e(keys %$scriptRegistry){
        next if($e eq 'url_self');
        if($scriptRegistry->{$e} eq $script || $scriptRegistry->{$e} =~ m/^$script\?/){
            $allowAccess=1; 
            last ;
       }
   
    }
    return $allowAccess;
 

}

########################################################################
1;
