package Opals::Eq_SolrSearch1;

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

# Version number
$VERSION   = 0.01;      

#use utf8;
use strict;
use Encode;
use LWP::UserAgent;
use HTTP::Request::Common;
use Time::localtime;
use JSON;

my $tm = localtime;

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>',
    eq_barcode => 'eq_barcode+<sortDir>'
};

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

my $eq_sortFieldMap={
    name =>'eq_name+<sortDir>,eq_manufacturer+<sortDir>,eq_model+<sortDir>,eq_rid+<sortDir>',
    eq_name =>'eq_name+<sortDir>,eq_manufacturer+<sortDir>,eq_model+<sortDir>,eq_rid+<sortDir>',
    #eq_name =>'eq_rid+<sortDir>',
    manufacturer => 'eq_manufacturer+<sortDir>,eq_name+<sortDir>,eq_model+<sortDir>,eq_rid+<sortDir>',
    eq_manufacturer => 'eq_manufacturer+<sortDir>,eq_name+<sortDir>,eq_model+<sortDir>,eq_rid+<sortDir>',
    model => 'eq_model+<sortDir>,eq_name+<sortDir>,eq_manufacturer+<sortDir>,eq_rid+<sortDir>',
    eq_model => 'eq_model+<sortDir>,eq_name+<sortDir>,eq_manufacturer+<sortDir>,eq_rid+<sortDir>',
    #eq_model => 'eq_model_sort+<sortDir>,eq_name_sort+<sortDir>,eq_manufacturer_sort+<sortDir>,eq_rid_sort+<sortDir>',
    barcode => 'eq_barcode+<sortDir>',
    eq_barcode => 'eq_barcode+<sortDir>'
};

my $eq_facetFieldMap = {
    category=>"eq_category_facet",
    building=>"eq_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;
}

################################################################################
# Search Solr
################################################################################

sub eq_slr_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 _querySolr{
    my($url)=@_;
    my $timeout = 600;
    my $userAgent = LWP::UserAgent->new(agent   => 'OPALS', timeout=>$timeout);
    my $request = HTTP::Request->new(GET => $url); 
    my $response = $userAgent->request($request );
    return $response->content;
}
################################################################################
# build Querry
sub eq_slr_srchQuery {
    my $this = shift;
    my ($input) = @_;

    my $luceneQuery ="fq=db:equipment&facet=true&facet.limit=-1";
    if ($input->{'groupBy'} eq "barcode"||$input->{'groupBy'} eq "eq_barcode"||$input->{'displayStyle'} eq 'linear'){
      $luceneQuery .= "&group.ngroups=true&group=true&group.field=eq_barcode";
      #$luceneQuery .= "&group.field=eq_barcode";
      $luceneQuery .= "&fl=eq_rid,eq_name,eq_model,eq_manufacturer,eq_barcode,rid";
    }
    else{
      $luceneQuery .= "&facet=true&group.ngroups=true&group=true&group.field=eq_rid";
      $luceneQuery .= "&fl=eq_rid,eq_name,eq_model,eq_manufacturer";
    }
    while (my ($k,$v) = each %{$eq_facetFieldMap}){
      #$luceneQuery .= "&facet.field=" . $v;
    }
    my $sTerm       = $input->{'kw'};
    my $sField      = $input->{'srchField'}||$input->{'sField'}||$input->{'sfield'};
    my $sExctMatch  = $input->{'exactmatch'}||0;
    my $sortAttr    = $input->{'sortAttr'};
    my $sortDir     = $input->{'sortOrder'};
    my $offset      = $input->{'offset'};
    my $pSize       = $input->{'pSize'};
    my $searchByCat = $input->{'searchByCat'};
    my $catCode     = $input->{'cat'};
    my $building    = $input->{'bldList'};
    my $notContain  = $input->{'notContain'};
    my $pSize       = $input->{'pSize'}|| 10;
    my $pNum        = $input->{'pNum'};
    my $rid         = $input->{'rid'};
    my $ridSel      = $input->{'ridSel'};
    open debug, ">/tmp/S"; 
    print debug "input:", to_json($input,{pretty=>1}), "\n";
    if (!defined $offset || $offset <=0){
      $offset = ($pNum - 1) * $pSize;
    }
    my ($catSearch,$simpleSearch,$advancedSearch) = (0,0,0);
    $catSearch = ($searchByCat  && $searchByCat > 0)? 1: 0;
    $simpleSearch = ($input->{'kw'} && $input->{'kw'} ne "") ? 1:0;
    $advancedSearch = ($input->{'kw1'} ne "" || $input->{'kw2'} ne "" || $input->{'kw3'} ne "")?1:0;
    print debug "sField: $sField\t sExctMatch:$sExctMatch\n";
    print debug "catSearch:$catSearch\t simpleSearch:$simpleSearch\t advancedSearch:$advancedSearch\n";
    if ($catSearch == 1) {
        if ($catCode && $catCode ne ""){
            $luceneQuery .= "&q=category:($catCode)";
        }
        else{
            $luceneQuery .= "&q=category:\*";
        }
    }
    elsif ($advancedSearch == 1){
        my ($sField1,$sField2,$sField3)= ("","","");
        my ($q,$q1,$q2,$q3)=("","","","");
        if ($input->{'kw1'} ne "" ){
            $q1=$input->{'sfield1'} . ":(" . $input->{'kw1'} . ") ";
        }
        if ($input->{'kw2'} ne "" ){
            $q2 .=$input->{'sfield2'} . ":(" . $input->{'kw2'} . ") ";
        }
        if ($input->{'kw3'} ne "" ){
            $q3 .=$input->{'sfield3'} . ":(" . $input->{'kw3'} . ")";
        }
        $q = $q1;
        if ($q2 ne "" && $q3 ne ""){
            $q .= uc($input->{'cfield1'}) . " (" . $q2 .  uc($input->{'cfield2'}) ." ". $q3 . ")";
        }
        elsif ($q2 ne "" ){
            $q .= uc($input->{'cfield1'}) . " ". $q2;
        }
        $luceneQuery .= "&q=$q";
    }
    else { #simple search
      print debug "sField:$sField \t 1)" , $sField eq '0',"2)\t" , $sField == 0, " \n";
        if (!$sField||$sField eq "0"){
            if ($sExctMatch && $sExctMatch eq "1"){
                $luceneQuery .= "&q=eq_anywhere_exct:(\"$sTerm\")";
            }else{
              print debug "HERE\n";
                $luceneQuery .= "&q=eq_anywhere:($sTerm)";
            }
        }
        else{
            if ($sExctMatch && $sExctMatch eq "1"){
                $luceneQuery .= "&q=". $sField ."_exct:(\"" . $sTerm ."\")";
            }else{
                if ($notContain && $notContain eq '1') {
                    $luceneQuery .= "&q=!$sField:($sTerm)";
                }
                else{
                    $luceneQuery .= "&q=$sField:($sTerm)";
                }
            }
        }
    }
    if (defined $building && $building ne "" && $building ne '0' ){
        $luceneQuery .= " AND 18:($building)";
    }
    $luceneQuery .= "&start=" . $offset . "&rows=" . $pSize;
    my $sortCond = $eq_sortFieldMap->{$sortAttr};
    if ($sortDir eq "1"){
        $sortDir = "asc";
    }
    else{
        $sortDir = "desc";
    }
    $sortCond =~ s/<sortDir>/$sortDir/g;
    $luceneQuery .= "&sort=$sortCond";
    #if ($input->{'wt'} eq "json"){
      $luceneQuery .= "&wt=json";
    #}
    print debug "luceneQuery:$luceneQuery \n";
    close debug;
    return "$luceneQuery";
}

sub eq_slr_search1 {
    my $this = shift;
    my $dbh     = $this->{'dbh'};
    my ($params)= @_;
    my ($hits,@result) = (0,());
    open debug ,">/tmp/SS";
    print debug "params from eq_slr_search1>>",to_json($params),"\n";
    if (!defined $params->{'lQuery'} || $params->{'lQuery'} eq ''){
        return {hits=>0,recordList=>undef};
    }
    my($sHost,$sPort,$sDatabase,$db_name) = $this->eq_slr_getSolrSrvInfo();
    my $url="http://$sHost:$sPort/solr/$db_name/select?" . $params->{'lQuery'} ;
    print debug "url:$url \n";
    my $data = _querySolr($url);
    print debug "data : ", $data , "\n";
    my $result = defined $data?decode_json($data):{};
=item    
    if ($params->{'displayStyle'} eq "linear"||$params->{'groupBy'} eq "eq_barcode"||$params->{'groupBy'} eq "barcode"){
        $hits = $result->{'grouped'}->{'eq_barcode'}->{'matches'} ;
    }
    else{
        $hits = $result->{'grouped'}->{'eq_rid'}->{'ngroups'} ;
    }
=cut
    $hits = $result->{'grouped'}->{'eq_rid'}->{'ngroups'} || $result->{'grouped'}->{'eq_barcode'}->{'matches'} ;
    my $facetList = getFacetListJson($result);
    #my $fieldMap = {};
    #my $recList = getRecordFieldsJson($dbh,$result,$fieldMap,$params->{'displayStyle'});
    my $recList = getRecords($dbh,$result,$params->{'groupBy'});
    close debug;
    return {hits=>$hits,recordList=>$recList,facetList=>$facetList};
}

sub getRecords {
    my ($dbh, $data,$groupBy) = @_;
    my $category =  getCategoryList($dbh);
    print debug "groupBy:\t$groupBy\n";
    print debug "data:\t", to_json($data,{pretty=>1}), "\n";
    my @recordList = ();
    my $record;
    my $rs= $data->{'grouped'}->{'eq_rid'}->{'groups'}||$data->{'grouped'}->{'eq_barcode'}->{'groups'};
    foreach my $rec (@{$rs}){
      $record=undef;
      foreach my $r(@{$rec->{'doclist'}->{'docs'}}){
        #what to do here......
        push @recordList, $r;
      }
    }
    return \@recordList;
}    
 
sub getSearchHits {
    my ($xml) = @_;
    my $hits=0;
    if($xml =~ m/<result name="response" numFound="([\d]+)" start="([\d]+)"\/*>/){
        $hits=$1;
    }
    else{
        if($xml =~ m/<int name="matches">([\d]+)<\/int>/){
            $hits=$1;
        }
    }
    return $hits;
}

sub getGroupFound {
    my ($xml) = @_;
    my $hits=0;
    #if($xml =~ m/<int name="matches">([\d]+)<\/int>/){
    #    $hits=$1;
    #}
    if($xml =~ m/<int name="ngroups">([\d]+)<\/int>/){
        $hits=$1;
    }
    return $hits;
}

sub getRecordIdList {
    my ($xml) = @_;
    my @rId = ();
    my $tmpXml = $xml;
    my $recXml="";
    while($tmpXml =~ m/<doc>(.*?)<\/doc>(.*)/s){
        $recXml=$1;
        $tmpXml=$2;
        if($recXml =~ m/<str name="rid">(.*?)<\/str>/s){
            push @rId, $1;
        }
    }
    return \@rId;
}

sub getFacetList {
    my ($xml) = @_;
    my $tmpXml;
    my $facetList=[];
    while (my ($k,$v) = each %{$facetFieldMap}){
        $tmpXml = $xml;
        if($tmpXml =~ /<lst name="$v">(.*?)<\/lst>/){
            $tmpXml = $1;
            my $fList=[];
            while($tmpXml =~ m/<int name="(.*?)">(.*?)<\/int>(.*)/s){
                my $fc=$1;
                $tmpXml = $3;
                push @$fList, {field=>$1,value=>$2} if ($fc ne '');
            }
            push @$facetList, {field=>$v,facetList=>$fList} ;   
        }
    }
    return $facetList;
}
sub getFacetListJson {
    my ($data) = @_;
    my $tmp;
    my $facetList=[];
    my $factet_fields = $data->{'facet_counts'}->{'facet_fields'};
    foreach my $ff (keys % {$factet_fields}){
      my %h = @{$factet_fields->{$ff}};
      my $fList = [];
      while (my ($k,$v) = each %h){ #remove key empty
        push @$fList, {field=>$k,value=>$v}  if ($k ne "");
      }
      push @$facetList, {field=>$ff,facetList=>$fList} ;
    }
    return $facetList;
}

sub getRsCategoryFacet {
    my ($xml) = @_;
    my $tmpXml = $xml;
    my $categoryFactList = [];
    if($tmpXml =~ /<lst name="category_facet">(.*?)<\/lst>/){
        $tmpXml = $1;
        while($tmpXml =~ m/<int name="(.*?)">(.*?)<\/int>(.*)/s){
            push @$categoryFactList, {
                field=>$1,
                value=>$2
            };
            $tmpXml = $3;
        }
    }
    return $categoryFactList;
}

sub getRsBuildingFacet {
    my ($xml) = @_;
    my $tmpXml = $xml;
    my $buildingFactList = [];
    if($tmpXml =~ /<lst name="building_facet">(.*?)<\/lst>/){
        $tmpXml = $1;
        while($tmpXml =~ m/<int name="(.*?)">(.*?)<\/int>(.*)/s){
            push @$buildingFactList, {
                field=>$1,
                value=>$2
            };
            $tmpXml = $3;
        }
    }
    return $buildingFactList;
}

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->{'adddress'};
            $list->{$b->{'code'}}->{'city'} = $b->{'city'};
            $list->{$b->{'code'}}->{'state'} = $b->{'state'};
        }
    }
    return $list;
}

sub getCategoryList {
    my ($dbh) = @_;
    my $sth = $dbh->prepare("select id,name from eq_category");
    my $list;
    $sth->execute();
    while (my $b = $sth->fetchrow_hashref()) {
        $list->{$b->{'id'}} = $b->{'name'};
    }
    return $list;
}

sub escapeXMLChars {
    my ($str) = @_;
    $str =~ s/&amp;/&/sg;
    $str =~ s/&lt;/</sg;
    $str =~ s/&gt;/>/sg;
    $str =~ s/&quot;/"/sg;
    $str =~ s/&apos;/'/sg;
    return $str;
}

sub getShowOnSearchFields {
    my ($dbh) = @_;
    my $sth = $dbh->prepare("select id,name, showOnSearch from eq_def where showOnSearch=1");
    my $list;
    $sth->execute();
    while (my $f = $sth->fetchrow_hashref()) {
        $list->{$f->{'id'}} = lc($f->{'id'});
    }
    return $list;
}
 
=item
sub getRecordFields {
    my ($dbh, $xml,$fieldMap) = @_;
    my $fieldMap = {
        rid             =>  "rid",
        eq_name         =>  "eq_name",
        category_facet  =>  "category",
        1               =>  "manufacturer",
        3               =>  "model",
        eq_barcode      =>  "barcode",
        5               =>  "serialNumber",
        38               => "status",
        11               => "location",
        41               => "assignedLName",
        46               => "cartNumber",
    };
    my $showOnSearchFieldMap = getShowOnSearchFields($dbh);
    $showOnSearchFieldMap->{'rid'}      = "rid";
    $showOnSearchFieldMap->{'eq_name'}  = "eq_name";
    $showOnSearchFieldMap->{'category_facet'}  =  "category";
    $showOnSearchFieldMap->{'eq_barcode'}  =  "barcode";
    $showOnSearchFieldMap->{'typeId'}  =  "typeId";
    my $category =  getCategoryList($dbh);
    my @recordList = ();
    my $record;
    my $tmpXml = $xml;
    my $recXml;
    my $fieldType="str|float|int|date";

    while ( $tmpXml =~ m/<doc>(.*?)<\/doc>(.*)/s ) {
        $recXml=$1;
        $tmpXml=$2;
        $record=undef;
        #foreach my $field(keys %{$fieldMap}){
        foreach my $field(keys %{$showOnSearchFieldMap}){
            if ($recXml =~ m/(<$fieldType) name="$field">(.*?)<\/($fieldType)>/s){
                $record->{$showOnSearchFieldMap->{$field}}= escapeXMLChars($2);
            }
            elsif($recXml =~ m/<arr name="$field">(.*?)<\/arr>/s){
                my $arrXml=$1;
                while($arrXml =~ m/<($fieldType)>(.*?)<\/($fieldType)>(.*)/s){
                    #push @{$record->{$fieldMap->{$field}}},{item=>$category->{$2}}  if ($1 eq $3);
                    push @{$record->{$showOnSearchFieldMap->{$field}}},{item=>$category->{$2}}  if ($1 eq $3);
                    $arrXml=$4;
                }
            }
        }
        push @recordList, $record if(defined $record);
    }
    return \@recordList;
}

sub getRecordFieldsJson {
    my ($dbh, $data,$fieldMap,$type) = @_;
    my $showOnSearchFieldMap = getShowOnSearchFields($dbh);
    $showOnSearchFieldMap->{'rid'}      = "rid";
    $showOnSearchFieldMap->{'eq_name'}  = "eq_name";
    $showOnSearchFieldMap->{'category_facet'}  =  "category";
    $showOnSearchFieldMap->{'eq_barcode'}  =  "barcode";
    $showOnSearchFieldMap->{'typeId'}  =  "typeId";
    my $category =  getCategoryList($dbh);
    my @recordList = ();
    my $record;
    #my $rs =($type eq 'linear')?$data->{'grouped'}->{'eq_barcode'}->{'groups'}:$data->{'grouped'}->{'rid'}->{'groups'};
    my $rs;
      $rs = $data->{'grouped'}->{'rid'}->{'groups'} || $data->{'grouped'}->{'eq_barcode'}->{'groups'} ;
    #foreach my $rec (@{$data->{'grouped'}->{'rid'}->{'groups'}}){
    foreach my $rec (@{$rs}){
      $record=undef;
      foreach my $field(keys %{$showOnSearchFieldMap}){
        foreach my $f(@{$rec->{'doclist'}->{'docs'}}){
          if ($field eq "category_facet"){
            $f->{$field} = $f->{$field} || [];
            $record->{'category'} = [] ;
            foreach my $c (@{$f->{$field}}){
              push @{$record->{'category'}},{item=>$c};
            }
          }
          $record->{$field} = $f->{$field} || "";
        }
      }
      push @recordList, $record if(defined $record);
    }
    return \@recordList;
}    
=cut
