/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.solr.client.solrj.response;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.beans.DocumentObjectBinder;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.params.CursorMarkParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;

/**
 * 
 *
 * @since solr 1.3
 */
@SuppressWarnings("unchecked")
public class QueryResponse extends SolrResponseBase 
{
  // Direct pointers to known types
  private NamedList<Object> _header = null;
  private SolrDocumentList _results = null;
  private NamedList<ArrayList> _sortvalues = null;
  private NamedList<Object> _facetInfo = null;
  private NamedList<Object> _debugInfo = null;
  private NamedList<Object> _highlightingInfo = null;
  private NamedList<NamedList<Object>> _spellInfo = null;
  private NamedList<Object> _statsInfo = null;
  private NamedList<NamedList<Number>> _termsInfo = null;
  private String _cursorMarkNext = null;

  // Grouping response
  private NamedList<Object> _groupedInfo = null;
  private GroupResponse _groupResponse = null;

  private NamedList<Object> _expandedInfo = null;
  private Map<String, SolrDocumentList> _expandedResults = null;

  // Facet stuff
  private Map<String,Integer> _facetQuery = null;
  private List<FacetField> _facetFields = null;
  private List<FacetField> _limitingFacets = null;
  private List<FacetField> _facetDates = null;
  private List<RangeFacet> _facetRanges = null;
  private NamedList<List<PivotField>> _facetPivot = null;
  private List<IntervalFacet> _intervalFacets = null;

  // Highlight Info
  private Map<String,Map<String,List<String>>> _highlighting = null;

  // SpellCheck Response
  private SpellCheckResponse _spellResponse = null;

  // Terms Response
  private TermsResponse _termsResponse = null;
  
  // Field stats Response
  private Map<String,FieldStatsInfo> _fieldStatsInfo = null;
  
  // Debug Info
  private Map<String,Object> _debugMap = null;
  private Map<String,String> _explainMap = null;

  // utility variable used for automatic binding -- it should not be serialized
  private transient final SolrServer solrServer;
  
  public QueryResponse(){
    solrServer = null;
  }
  
  /**
   * Utility constructor to set the solrServer and namedList
   */
  public QueryResponse( NamedList<Object> res , SolrServer solrServer){
    this.setResponse( res );
    this.solrServer = solrServer;
  }

  @Override
  public void setResponse( NamedList<Object> res )
  {
    super.setResponse( res );
    
    // Look for known things
    for( int i=0; i<res.size(); i++ ) {
      String n = res.getName( i );
      if( "responseHeader".equals( n ) ) {
        _header = (NamedList<Object>) res.getVal( i );
      }
      else if( "response".equals( n ) ) {
        _results = (SolrDocumentList) res.getVal( i );
      }
      else if( "sort_values".equals( n ) ) {
        _sortvalues = (NamedList<ArrayList>) res.getVal( i );
      }
      else if( "facet_counts".equals( n ) ) {
        _facetInfo = (NamedList<Object>) res.getVal( i );
        // extractFacetInfo inspects _results, so defer calling it
        // in case it hasn't been populated yet.
      }
      else if( "debug".equals( n ) ) {
        _debugInfo = (NamedList<Object>) res.getVal( i );
        extractDebugInfo( _debugInfo );
      }
      else if( "grouped".equals( n ) ) {
        _groupedInfo = (NamedList<Object>) res.getVal( i );
        extractGroupedInfo( _groupedInfo );
      }
      else if("expanded".equals(n)) {
        _expandedResults = (Map<String, SolrDocumentList>) res.getVal( i );
      }
      else if( "highlighting".equals( n ) ) {
        _highlightingInfo = (NamedList<Object>) res.getVal( i );
        extractHighlightingInfo( _highlightingInfo );
      }
      else if ( "spellcheck".equals( n ) )  {
        _spellInfo = (NamedList<NamedList<Object>>) res.getVal( i );
        extractSpellCheckInfo( _spellInfo );
      }
      else if ( "stats".equals( n ) )  {
        _statsInfo = (NamedList<Object>) res.getVal( i );
        extractStatsInfo( _statsInfo );
      }
      else if ( "terms".equals( n ) ) {
        _termsInfo = (NamedList<NamedList<Number>>) res.getVal( i );
        extractTermsInfo( _termsInfo );
      }
      else if ( CursorMarkParams.CURSOR_MARK_NEXT.equals( n ) ) {
        _cursorMarkNext = (String) res.getVal( i );
      }
    }
    if(_facetInfo != null) extractFacetInfo( _facetInfo );
  }

  private void extractSpellCheckInfo(NamedList<NamedList<Object>> spellInfo) {
    _spellResponse = new SpellCheckResponse(spellInfo);
  }

  private void extractTermsInfo(NamedList<NamedList<Number>> termsInfo) {
    _termsResponse = new TermsResponse(termsInfo);
  }
  
  private void extractStatsInfo(NamedList<Object> info) {
    if( info != null ) {
      _fieldStatsInfo = new HashMap<>();
      NamedList<NamedList<Object>> ff = (NamedList<NamedList<Object>>) info.get( "stats_fields" );
      if( ff != null ) {
        for( Map.Entry<String,NamedList<Object>> entry : ff ) {
          NamedList<Object> v = entry.getValue();
          if( v != null ) {
            _fieldStatsInfo.put( entry.getKey(), 
                new FieldStatsInfo( v, entry.getKey() ) );
          }
        }
      }
    }
  }

  private void extractDebugInfo( NamedList<Object> debug )
  {
    _debugMap = new LinkedHashMap<>(); // keep the order
    for( Map.Entry<String, Object> info : debug ) {
      _debugMap.put( info.getKey(), info.getValue() );
    }

    // Parse out interesting bits from the debug info
    _explainMap = new HashMap<>();
    NamedList<String> explain = (NamedList<String>)_debugMap.get( "explain" );
    if( explain != null ) {
      for( Map.Entry<String, String> info : explain ) {
        String key = info.getKey();
        _explainMap.put( key, info.getValue() );
      }
    }
  }

  private void extractGroupedInfo( NamedList<Object> info ) {
    if ( info != null ) {
      _groupResponse = new GroupResponse();
      int size = info.size();
      for (int i=0; i < size; i++) {
        String fieldName = info.getName(i);
        Object fieldGroups =  info.getVal(i);
        SimpleOrderedMap<Object> simpleOrderedMap = (SimpleOrderedMap<Object>) fieldGroups;

        Object oMatches = simpleOrderedMap.get("matches");
        Object oNGroups = simpleOrderedMap.get("ngroups");
        Object oGroups = simpleOrderedMap.get("groups");
        Object queryCommand = simpleOrderedMap.get("doclist");
        if (oMatches == null) {
          continue;
        }

        if (oGroups != null) {
          Integer iMatches = (Integer) oMatches;
          ArrayList<Object> groupsArr = (ArrayList<Object>) oGroups;
          GroupCommand groupedCommand;
          if (oNGroups != null) {
            Integer iNGroups = (Integer) oNGroups;
            groupedCommand = new GroupCommand(fieldName, iMatches, iNGroups);
          } else {
            groupedCommand = new GroupCommand(fieldName, iMatches);
          }

          for (Object oGrp : groupsArr) {
            SimpleOrderedMap grpMap = (SimpleOrderedMap) oGrp;
            Object sGroupValue = grpMap.get( "groupValue");
            SolrDocumentList doclist = (SolrDocumentList) grpMap.get( "doclist");
            Group group = new Group(sGroupValue != null ? sGroupValue.toString() : null, doclist) ;
            groupedCommand.add(group);
          }

          _groupResponse.add(groupedCommand);
        } else if (queryCommand != null) {
          Integer iMatches = (Integer) oMatches;
          GroupCommand groupCommand;
          if (oNGroups != null) {
            Integer iNGroups = (Integer) oNGroups;
            groupCommand = new GroupCommand(fieldName, iMatches, iNGroups);
          } else {
            groupCommand = new GroupCommand(fieldName, iMatches);
          }
          SolrDocumentList docList = (SolrDocumentList) queryCommand;
          groupCommand.add(new Group(fieldName, docList));
          _groupResponse.add(groupCommand);
        }
      }
    }
  }

  private void extractHighlightingInfo( NamedList<Object> info )
  {
    _highlighting = new HashMap<>();
    for( Map.Entry<String, Object> doc : info ) {
      Map<String,List<String>> fieldMap = new HashMap<>();
      _highlighting.put( doc.getKey(), fieldMap );
      
      NamedList<List<String>> fnl = (NamedList<List<String>>)doc.getValue();
      for( Map.Entry<String, List<String>> field : fnl ) {
        fieldMap.put( field.getKey(), field.getValue() );
      }
    }
  }

  private void extractFacetInfo( NamedList<Object> info )
  {
    // Parse the queries
    _facetQuery = new LinkedHashMap<>();
    NamedList<Integer> fq = (NamedList<Integer>) info.get( "facet_queries" );
    if (fq != null) {
      for( Map.Entry<String, Integer> entry : fq ) {
        _facetQuery.put( entry.getKey(), entry.getValue() );
      }
    }
    
    // Parse the facet info into fields
    // TODO?? The list could be <int> or <long>?  If always <long> then we can switch to <Long>
    NamedList<NamedList<Number>> ff = (NamedList<NamedList<Number>>) info.get( "facet_fields" );
    if( ff != null ) {
      _facetFields = new ArrayList<>( ff.size() );
      _limitingFacets = new ArrayList<>( ff.size() );
      
      long minsize = _results == null ? Long.MAX_VALUE :_results.getNumFound();
      for( Map.Entry<String,NamedList<Number>> facet : ff ) {
        FacetField f = new FacetField( facet.getKey() );
        for( Map.Entry<String, Number> entry : facet.getValue() ) {
          f.add( entry.getKey(), entry.getValue().longValue() );
        }
        
        _facetFields.add( f );
        FacetField nl = f.getLimitingFields( minsize );
        if( nl.getValueCount() > 0 ) {
          _limitingFacets.add( nl );
        }
      }
    }
    
    //Parse date facets
    NamedList<NamedList<Object>> df = (NamedList<NamedList<Object>>) info.get("facet_dates");
    if (df != null) {
      // System.out.println(df);
      _facetDates = new ArrayList<>( df.size() );
      for (Map.Entry<String, NamedList<Object>> facet : df) {
        // System.out.println("Key: " + facet.getKey() + " Value: " + facet.getValue());
        NamedList<Object> values = facet.getValue();
        String gap = (String) values.get("gap");
        Date end = (Date) values.get("end");
        FacetField f = new FacetField(facet.getKey(), gap, end);
        
        for (Map.Entry<String, Object> entry : values)   {
          try {
            f.add(entry.getKey(), Long.parseLong(entry.getValue().toString()));
          } catch (NumberFormatException e) {
            //Ignore for non-number responses which are already handled above
          }
        }
        
        _facetDates.add(f);
      }
    }

    //Parse range facets
    NamedList<NamedList<Object>> rf = (NamedList<NamedList<Object>>) info.get("facet_ranges");
    if (rf != null) {
      _facetRanges = new ArrayList<>( rf.size() );
      for (Map.Entry<String, NamedList<Object>> facet : rf) {
        NamedList<Object> values = facet.getValue();
        Object rawGap = values.get("gap");

        RangeFacet rangeFacet;
        if (rawGap instanceof Number) {
          Number gap = (Number) rawGap;
          Number start = (Number) values.get("start");
          Number end = (Number) values.get("end");

          Number before = (Number) values.get("before");
          Number after = (Number) values.get("after");
          Number between = (Number) values.get("between");

          rangeFacet = new RangeFacet.Numeric(facet.getKey(), start, end, gap, before, after, between);
        } else {
          String gap = (String) rawGap;
          Date start = (Date) values.get("start");
          Date end = (Date) values.get("end");

          Number before = (Number) values.get("before");
          Number after = (Number) values.get("after");
          Number between = (Number) values.get("between");

          rangeFacet = new RangeFacet.Date(facet.getKey(), start, end, gap, before, after, between);
        }

        NamedList<Integer> counts = (NamedList<Integer>) values.get("counts");
        for (Map.Entry<String, Integer> entry : counts)   {
          rangeFacet.addCount(entry.getKey(), entry.getValue());
        }

        _facetRanges.add(rangeFacet);
      }
    }
    
    //Parse pivot facets
    NamedList pf = (NamedList) info.get("facet_pivot");
    if (pf != null) {
      _facetPivot = new NamedList<>();
      for( int i=0; i<pf.size(); i++ ) {
        _facetPivot.add( pf.getName(i), readPivots( (List<NamedList>)pf.getVal(i) ) );
      }
    }
    
    //Parse interval facets
    NamedList<NamedList<Object>> intervalsNL = (NamedList<NamedList<Object>>) info.get("facet_intervals");
    if (intervalsNL != null) {
      _intervalFacets = new ArrayList<>(intervalsNL.size());
      for (Map.Entry<String, NamedList<Object>> intervalField : intervalsNL) {
        String field = intervalField.getKey();
        List<IntervalFacet.Count> counts = new ArrayList<IntervalFacet.Count>(intervalField.getValue().size());
        for (Map.Entry<String, Object> interval : intervalField.getValue()) {
          counts.add(new IntervalFacet.Count(interval.getKey(), (Integer)interval.getValue()));
        }
        _intervalFacets.add(new IntervalFacet(field, counts));
      }
    }
  }
  
  protected List<PivotField> readPivots( List<NamedList> list )
  {
    ArrayList<PivotField> values = new ArrayList<>( list.size() );
    for( NamedList nl : list ) {
      // NOTE, this is cheating, but we know the order they are written in, so no need to check
      assert "field".equals(nl.getName(0));
      String f = (String)nl.getVal( 0 );
      assert "value".equals(nl.getName(1));
      Object v = nl.getVal( 1 );
      assert "count".equals(nl.getName(2));
      int cnt = ((Integer)nl.getVal( 2 )).intValue();
      List<PivotField> p = null;
      if (4 <= nl.size()) {
        assert "pivot".equals(nl.getName(3));
        Object subPiv = nl.getVal(3);
        assert null != subPiv : "Server sent back 'null' for sub pivots?";
        p = readPivots( (List<NamedList>) subPiv );
      }
      values.add( new PivotField( f, v, cnt, p ) );
    }
    return values;
  }

  //------------------------------------------------------
  //------------------------------------------------------

  /**
   * Remove the field facet info
   */
  public void removeFacets() {
    _facetFields = new ArrayList<>();
  }
  
  //------------------------------------------------------
  //------------------------------------------------------

  public NamedList<Object> getHeader() {
    return _header;
  }

  public SolrDocumentList getResults() {
    return _results;
  }
 
  public NamedList<ArrayList> getSortValues(){
    return _sortvalues;
  }

  public Map<String, Object> getDebugMap() {
    return _debugMap;
  }

  public Map<String, String> getExplainMap() {
    return _explainMap;
  }

  public Map<String,Integer> getFacetQuery() {
    return _facetQuery;
  }

  public Map<String, SolrDocumentList> getExpandedResults(){
    return this._expandedResults;
  }

  /**
   * Returns the {@link GroupResponse} containing the group commands.
   * A group command can be the result of one of the following parameters:
   * <ul>
   *   <li>group.field
   *   <li>group.func
   *   <li>group.query
   * </ul>
   *
   * @return the {@link GroupResponse} containing the group commands
   */
  public GroupResponse getGroupResponse() {
    return _groupResponse;
  }
  
  public Map<String, Map<String, List<String>>> getHighlighting() {
    return _highlighting;
  }

  public SpellCheckResponse getSpellCheckResponse() {
    return _spellResponse;
  }

  public TermsResponse getTermsResponse() {
    return _termsResponse;
  }
  
  /**
   * See also: {@link #getLimitingFacets()}
   */
  public List<FacetField> getFacetFields() {
    return _facetFields;
  }
  
  public List<FacetField> getFacetDates()   {
    return _facetDates;
  }

  public List<RangeFacet> getFacetRanges() {
    return _facetRanges;
  }

  public NamedList<List<PivotField>> getFacetPivot()   {
    return _facetPivot;
  }
  
  public List<IntervalFacet> getIntervalFacets() {
    return _intervalFacets;
  }
  
  /** get
   * 
   * @param name the name of the
   * @return the FacetField by name or null if it does not exist
   */
  public FacetField getFacetField(String name) {
    if (_facetFields==null) return null;
    for (FacetField f : _facetFields) {
      if (f.getName().equals(name)) return f;
    }
    return null;
  }
  
  public FacetField getFacetDate(String name)   {
    if (_facetDates == null)
      return null;
    for (FacetField f : _facetDates)
      if (f.getName().equals(name))
        return f;
    return null;
  }
  
  /**
   * @return a list of FacetFields where the count is less then
   * then #getResults() {@link SolrDocumentList#getNumFound()}
   * 
   * If you want all results exactly as returned by solr, use:
   * {@link #getFacetFields()}
   */
  public List<FacetField> getLimitingFacets() {
    return _limitingFacets;
  }
  
  public <T> List<T> getBeans(Class<T> type){
    return solrServer == null ? 
      new DocumentObjectBinder().getBeans(type,_results):
      solrServer.getBinder().getBeans(type, _results);
  }

  public Map<String, FieldStatsInfo> getFieldStatsInfo() {
    return _fieldStatsInfo;
  }

  public String getNextCursorMark() {
    return _cursorMarkNext;
  }
}



