package Opals::Eq_SolrIndex;

#require Exporter;
#@ISA       = qw(Exporter);

# Version number
$VERSION   = 0.01;      
use utf8;

#use utf8;
use strict;
use Encode;
use JSON;
use LWP::UserAgent;
use HTTP::Request::Common;
use Time::localtime;
use constant IND_UPDATE_BATCH_SIZE => 20;
use Opals::Equipment qw(
    eq_categoryMapList
);

my $tm = localtime;
my $dateToday = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $tm->year+1900, ($tm->mon)+1, $tm->mday, $tm->hour, $tm->min, $tm->sec);

my $sortFieldMap={
    eq_name =>'eq_name_sort+<sortDir>,1_sort+<sortDir>,3_sort+<sortDir>,rid_sort+<sortDir>',
    1 => '1_sort+<sortDir>,eq_name_sort+<sortDir>,3_sort+<sortDir>,rid_sort+<sortDir>',
    3 => '3_sort+<sortDir>,eq_name_sort+<sortDir>,1_sort+<sortDir>,rid_sort+<sortDir>',
};

my $facetFieldMap = {
    category=>"category_facet",
    building=>"building_facet"
};

sub new {
    my $class = shift;
    my (%param) = (@_);
    my $dbh = $param{'dbh'};
    return unless $dbh;
    my $this = {
        dbh => $dbh,
    };
    bless $this, $class;
    return $this;
}
################################################################################
# Indexer 
# build docs get input from database (_getDataFromDB())
# 2018-08-24 09:18:33 EDT, Fri Aug -- 
sub eq_slr_updateIndex {
    my $this = shift;
    my $dbh = $this->{'dbh'};
    my($sHost,$sPort,$sDatabase,$db_name) = $this->eq_getSolrSrvInfo();
    my $url = "http://$sHost:$sPort/solr/$db_name/update/json";
    my $httpReq = HTTP::Request->new(POST => $url);
    $httpReq->content_type('Content-type:application/json; charset=utf-8');
    my $response  = undef;
    my $ua = LWP::UserAgent->new(agent=>'SolrHTTPUpdateHandlerAgent');
    $ua->timeout(600);
    my $succeed   = 1;
    my $count = 0;
    my $catMapList = Opals::Equipment::eq_categoryMapList($dbh);
    my $ridList = $this->eq_getRidList_update();
    while (scalar(@$ridList) > 0) {
      my $ridListStr = join (",", @$ridList);
      my $rs = $this->_getDataFromDB({ridList=>$ridListStr});
      my $data = $this->_parseDocFromRecordList({recordset=>$rs,catMapList=>$catMapList}); 
      $httpReq->content(to_json($data));
      $response = $ua->request($httpReq);
      if ($response->is_error() || !$response->is_success()) {
        $succeed=0;
        last;
      }
      $dbh->do("update eq_records set indexed='1' where rid in ($ridListStr)");
      $ridList = $this->eq_getRidList_update();
      $count++;
    }
    if ($succeed && $count > 0) {
      $httpReq->content("{commit:{}}");
      $response = $ua->request($httpReq);
      if ($response->is_success) {
      }
    }
    $dbh->do("update eq_csvImport set status='done' where (countImported>0 && countImported=countProcessed) && (status='indexing')");
}

sub _getDataFromDB {
    my $this = shift;
    my $dbh = $this->{'dbh'};
    my ($params) = @_;
    my $buildings = getBuildingList($dbh);
    my $sql = <<_SQL_;
select r.rid,r.rname as name,r.category,r.container,
    i.iid, i.barcode,i.typeId,i.copyNo,i.available
from eq_records r 
inner join eq_items i on r.rid=i.rid && r.deleted='0' && i.deleted='0'
where r.indexed='0' 
_SQL_
    my $sqlr = <<_SQLR_;
select d.id as id ,fId,fValue  
from eq_def d left outer join eq_recordFields r on d.id=r.fId && r.rid=?
where d.defType='record' 
_SQLR_
    my $sqli = <<_SQLI_;
select d.id as id, sfId, replace(replace(sfValue,CHAR(194),''),CHAR(160),'') as sfValue 
from eq_def d left outer join  eq_itemFields itf on d.id=itf.sfId && itf.rid=? && itf.iid=? 
where d.defType='item' 
_SQLI_
if (defined $params && $params->{'ridList'} ne "")  {
        $sql .= " && r.rid in (" . $params->{'ridList'} . ") ";
    }
    my @rs = ();  
    my $sth = $dbh->prepare($sql);
    my $sth_r = $dbh->prepare($sqlr);
    my $sth_i = $dbh->prepare($sqli);
    $sth->execute();
    while (my $rec = $sth->fetchrow_hashref()){
        $sth_r->execute($rec->{'rid'});
        my @rf = ();
        while (my $r = $sth_r->fetchrow_hashref()){
          if ($r->{'fValue'} && $r->{'fValue'} ne "") {
            push @rf, {
                $r->{'id'} => ($r->{'fValue'})?$r->{'fValue'}:""
            }
          }
        }
        my @itf =();
        my $bldCode= "";
        $sth_i->execute($rec->{'rid'},$rec->{'iid'});
        while(my $i = $sth_i->fetchrow_hashref()){
           if ($i->{'sfValue'} && $i->{'sfValue'} ne "") {
              push @itf, {
                  $i->{'id'} => ($i->{'sfValue'})?$i->{'sfValue'}:""
              };
              if ($i->{'id'} eq '18' && $i->{'sfValue'} ne "" && $bldCode eq ""){  
                  $bldCode = ($i->{'sfValue'})?$i->{'sfValue'}:"";    
              }
           }
        }
        if ($bldCode ne ""){
            push @itf, {"bldCode"   => $bldCode };
            push @itf, {"bldName"   => $buildings->{$bldCode}->{'name'} || "" };
            push @itf, {"bldAddress"=> $buildings->{$bldCode}->{'address'}  || ""};
            push @itf, {"bldCity"   => $buildings->{$bldCode}->{'city'} || "" };
            push @itf, {"bldState"  => $buildings->{$bldCode}->{'state'} || ""};
        };
        push @rs , {
            rid     => $rec->{'rid'},
            eq_name  => $rec->{'name'},
            category=> $rec->{'category'},
            container=> $rec->{'container'},
            eq_barcode => ($rec->{'barcode'})? $rec->{'barcode'}:$rec->{'rid'} . "_NOBC",
            id => ($rec->{'barcode'})? $rec->{'barcode'}:$rec->{'rid'} . "_NOBC",
            iid     => $rec->{'iid'},
            typeId  => $rec->{'typeId'},
            copyNo  => ($rec->{'copyNo'})?$rec->{'copyNo'}:"",
            available=>$rec->{'available'},
            rfs     => \@rf,
            itfs    => \@itf,
        };
    }
    $sth->finish;
    $sth_r->finish;
    return \@rs;
}
sub _parseDocFromRecordList {
  my $this = shift;
  my $dbh = $this->{'dbh'};
  my ($params) = @_;
  my $data = $params->{'recordset'};
  my $catMapList = $params->{'catMapList'};
  my @ret = ();
  my $tmpH = {};
  foreach my $d(@{$data}){
    $tmpH = {};
    foreach my $k(keys %{$d}){
      if ($k eq 'category' && $d->{$k} ne ""){
        $tmpH->{$k} = [];
        my @tmp = split (/,/,$d->{$k});
        foreach my $t (@tmp){
         push @{$tmpH->{$k}}, $catMapList->{$t};
         push @{$tmpH->{'categorySrch'}}, $catMapList->{$t};
        }
      }
      elsif ($k eq 'rfs' || $k eq 'itfs'){
        foreach my $dd (@{$d->{$k}}){
          foreach my $kk(keys %{$dd}){
            $tmpH->{$kk}=$dd->{$kk} ;
          }
        }
      }
      else{
        $tmpH->{$k}=$d->{$k} ;
      }
    }
   $tmpH->{'db'}="equipment";
   push @ret,$tmpH;
  }
  return \@ret;
}

sub _postRequest {
    my $this = shift;
    my ($data) = @_;
    my($sHost,$sPort,$sDatabase,$db_name) = $this->eq_getSolrSrvInfo();
    my $url = "http://$sHost:$sPort/solr/$db_name/update/json";
    my $httpReq = HTTP::Request->new(POST => $url);
    $httpReq->content_type('Content-type:application/json; charset=utf-8');
    my $response  = undef;
    my $ua = LWP::UserAgent->new(agent=>'SolrHTTPUpdateHandlerAgent');
    $ua->timeout(600);
    $httpReq->content($data);
    $response = $ua->request($httpReq);
    return $response->is_success;
}

sub _getDeletedBarcodeList {
    my $this = shift;
    my $dbh = $this->{'dbh'};
    my ($params) = @_;
    my $size = $params->{'size'} || 1;
    my @list = ();
    my $sql = "select i.rid,i.barcode from eq_items i inner join eq_records r using(rid) where i.deleted ='1' && r.indexed='0' limit $size";
    my $sth = $dbh->prepare($sql);
    $sth->execute();
    while ( my ($rid,$barcode) = $sth->fetchrow_array){
        $barcode =~ s/^_*(.+?)(_[\d]+)?$/$1/;
        push @list, {
            rid     => $rid,
            barcode => $barcode
        };
    }
    return \@list;
}

sub eq_solrIndex_cleanByRId {
  my $this = shift;
  my $dbh = $this->{'dbh'};
  my ($rid) = @_;
  my($sHost,$sPort,$sDatabase,$db_name) = eq_getSolrSrvInfo();
  my $ua = LWP::UserAgent->new(agent=>'SolrHTTPUpdateHandlerAgent');
  $ua->timeout(600);
  my $url = "http://$sHost:$sPort/solr/$db_name/update/json";
  my $httpReq = HTTP::Request->new(POST => $url);
  $httpReq->content_type('Content-type:application/json; charset=utf-8');
  my $delQryFmt = "{delete:{query:'db:(equipment) AND rid:%d'}}";
  $httpReq->content(sprintf($delQryFmt,$rid));
  my $response = $ua->request($httpReq);
  $httpReq->content("{commit:{}}");
}
sub eq_solrIndex_cleanByBarcode {
  my $this = shift;
  my $dbh = $this->{'dbh'};
  my ($barcode) = @_;
  my($sHost,$sPort,$sDatabase,$db_name) = eq_getSolrSrvInfo();
  my $ua = LWP::UserAgent->new(agent=>'SolrHTTPUpdateHandlerAgent');
  $ua->timeout(600);
  my $url = "http://$sHost:$sPort/solr/$db_name/update/json";
  my $httpReq = HTTP::Request->new(POST => $url);
  $httpReq->content_type('Content-type:application/json; charset=utf-8');
  my $delQryFmt = "{delete:{query:'db:(equipment) AND eq_barcode:%s'}}";
  $httpReq->content(sprintf($delQryFmt,$barcode));
  my $response = $ua->request($httpReq);
  $httpReq->content("{commit:{}}");
}

sub eq_solrIndex_clean_bk {
  my $this = shift;
  my $dbh = $this->{'dbh'};
  my($sHost,$sPort,$sDatabase,$db_name) = eq_getSolrSrvInfo();
  my $url = "http://$sHost:$sPort/solr/$db_name/update/json";
  my $httpReq = HTTP::Request->new(POST => $url);
  #$httpReq->content_type('Content-type:application/json;');
  $httpReq->content("{delete:{query:'db:(equipment) AND *:*'}}");
  $httpReq->content("{commit:{}}");
  my $ua = LWP::UserAgent->new(agent=>'SolrHTTPUpdateHandlerAgent');
  $ua->timeout(600);
  my $response = $ua->request($httpReq);
      if ($response->is_success) {
        $dbh->do("update eq_records set indexed='0' where deleted='0' && indexed='1' && rid<=10");
      }
}
sub eq_solrIndex_clean {
  eq_slr_index_clean();
}
sub eq_slr_index_clean {
  my $this = shift;
  my $dbh = $this->{'dbh'};
  my($sHost,$sPort,$sDatabase,$db_name) = eq_getSolrSrvInfo();
  my $url = "http://$sHost:$sPort/solr/$db_name/update/json";
  my $ua = LWP::UserAgent->new(agent=>'SolrHTTPUpdateHandlerAgent');
  $ua->timeout(600);
  my $httpReq = HTTP::Request->new(POST => $url);
  $httpReq->content_type('Content-type:application/json; charset=utf-8');
  #$httpReq->content("{delete:{query:'db:(equipment) AND *:*'}}");
  my $delQryFmt ="{delete:{query:'db:(equipment) AND *:*'} }";
  $httpReq->content(sprintf($delQryFmt));
  my $response = $ua->request($httpReq);
  $httpReq->content("{commit:{}}");
  $response = $ua->request($httpReq);
  #my $response = $ua->request($httpReq);
  if ($response->is_success) {
    $dbh->do("update eq_records set indexed='0' where indexed='1'");
  }
}

sub eq_getSolrSrvInfo {
    my $sHost   = Opals::Context->config('sHost');
    my $sPort   = Opals::Context->config('sPort');
    my $sDatabase = Opals::Context->config('zDatabase');
    my $db_name = Opals::Context->config('db_name');
    return ($sHost,$sPort,$sDatabase,$db_name);
}

sub eq_getRidList_update {
    my $this = shift;
    my $dbh = $this->{'dbh'};
    my $sth = $dbh->prepare("select rid from eq_records where indexed ='0' order by rid limit 10");
    my @ridList = ();
    $sth->execute();
    while(my $rec = $sth->fetchrow_hashref){
        push @ridList, $rec->{'rid'};
    }
    return \@ridList;
}

sub getBuildingList {
    my ($dbh) = @_;
    my $sql= <<_SQL_;
select code,name,address,city,state from eq_locationDirectory order by code;
_SQL_
    my $sth = $dbh->prepare($sql);
    my $list;
    $sth->execute();
    while (my $b = $sth->fetchrow_hashref()) {
        if (!$list->{$b->{'code'}}){
            $list->{$b->{'code'}}->{'code'} = $b->{'code'};
            $list->{$b->{'code'}}->{'name'} = $b->{'name'};
            $list->{$b->{'code'}}->{'address'} = $b->{'address'};
            $list->{$b->{'code'}}->{'city'} = $b->{'city'};
            $list->{$b->{'code'}}->{'state'} = $b->{'state'};
        }
    }
    return $list;
}

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



