/*
 * 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 java.util.TreeMap;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.beans.DocumentObjectBinder;
import org.apache.solr.client.solrj.response.json.NestableJsonFacet;
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<Object> _spellInfo = null;
  private List<NamedList<Object>> _clusterInfo = null;
  private NamedList<Object> _jsonFacetingInfo = null;
  private Map<String,NamedList<Object>> _suggestInfo = null;
  private NamedList<Object> _statsInfo = null;
  private NamedList<NamedList<Object>> _termsInfo = null;
  private NamedList<SolrDocumentList> _moreLikeThisInfo = 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;

  // Clustering Response
  private ClusteringResponse _clusterResponse = null;

  // Json Faceting Response
  private NestableJsonFacet _jsonFacetingResponse = null;

  // Suggester Response
  private SuggesterResponse _suggestResponse = 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,Object> _explainMap = null;

  // utility variable used for automatic binding -- it should not be serialized
  private transient final SolrClient solrClient;

  public QueryResponse() {
    solrClient = null;
  }
  
  /**
   * Utility constructor to set the solrServer and namedList
   */
  public QueryResponse( NamedList<Object> res , SolrClient solrClient){
    this.setResponse( res );
    this.solrClient = solrClient;
  }

  public QueryResponse(SolrClient solrClient) {
    this.solrClient = solrClient;
  }

  @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)) {
        NamedList map = (NamedList) res.getVal(i);
        _expandedResults = map.asMap(1);
      }
      else if( "highlighting".equals( n ) ) {
        _highlightingInfo = (NamedList<Object>) res.getVal( i );
        extractHighlightingInfo( _highlightingInfo );
      }
      else if ( "spellcheck".equals( n ) )  {
        _spellInfo = (NamedList<Object>) res.getVal( i );
        extractSpellCheckInfo( _spellInfo );
      }
      else if ("clusters".equals(n)) {
        _clusterInfo = (ArrayList<NamedList<Object>>) res.getVal(i);
        extractClusteringInfo(_clusterInfo);
      }
      else if ("facets".equals(n)) {
        _jsonFacetingInfo = (NamedList<Object>) res.getVal(i);
        // Don't call extractJsonFacetingInfo(_jsonFacetingInfo) here in an effort to do it lazily
      }
      else if ( "suggest".equals( n ) )  {
        _suggestInfo = (Map<String,NamedList<Object>>) res.getVal( i );
        extractSuggesterInfo(_suggestInfo);
      }
      else if ( "stats".equals( n ) )  {
        _statsInfo = (NamedList<Object>) res.getVal( i );
        extractStatsInfo( _statsInfo );
      }
      else if ( "terms".equals( n ) ) {
        _termsInfo = (NamedList<NamedList<Object>>) res.getVal( i );
        extractTermsInfo( _termsInfo );
      }
      else if ( "moreLikeThis".equals( n ) ) {
        _moreLikeThisInfo = (NamedList<SolrDocumentList>) res.getVal( i );
      }
      else if ( CursorMarkParams.CURSOR_MARK_NEXT.equals( n ) ) {
        _cursorMarkNext = (String) res.getVal( i );
      }
    }
    if(_facetInfo != null) extractFacetInfo( _facetInfo );
  }

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

  private void extractClusteringInfo(List<NamedList<Object>> clusterInfo) {
    _clusterResponse = new ClusteringResponse(clusterInfo);
  }

  private void extractJsonFacetingInfo(NamedList<Object> facetInfo) {
    _jsonFacetingResponse = new NestableJsonFacet(facetInfo);
  }

  private void extractSuggesterInfo(Map<String, NamedList<Object>> suggestInfo) {
    _suggestResponse = new SuggesterResponse(suggestInfo);
  }

  private void extractTermsInfo(NamedList<NamedList<Object>> termsInfo) {
    _termsResponse = new TermsResponse(termsInfo);
  }
  
  private void extractStatsInfo(NamedList<Object> info) {
    _fieldStatsInfo = extractFieldStatsInfo(info);
  }

  private Map<String, FieldStatsInfo> extractFieldStatsInfo(NamedList<Object> info) {
    if( info != null ) {
       Map<String, FieldStatsInfo> fieldStatsInfoMap = new TreeMap<>();
      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 ) {
             fieldStatsInfoMap.put( entry.getKey(),
                new FieldStatsInfo( v, entry.getKey() ) );
          }
        }
      }
       return fieldStatsInfoMap;
    }
    return null;
  }

  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<Object> explain = (NamedList<Object>)_debugMap.get( "explain" );
    if( explain != null ) {
      for( Map.Entry<String, Object> 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) {
          Long iMatches = oMatches==null? null: ((Number) oMatches).longValue();
          ArrayList<Object> groupsArr = (ArrayList<Object>) oGroups;
          GroupCommand groupedCommand;
          if (oNGroups != null) {
            Long iNGroups = oNGroups==null? null: ((Number) oNGroups).longValue();
            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) {
          Long iMatches = oMatches==null? null: ((Number) oMatches).longValue();
          GroupCommand groupCommand;
          if (oNGroups != null) {
            Long iNGroups = oMatches==null? null: ((Number) oNGroups).longValue();;
            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 range facets
    NamedList<NamedList<Object>> rf = (NamedList<NamedList<Object>>) info.get("facet_ranges");
    if (rf != null) {
      _facetRanges = extractRangeFacets(rf);
    }
    
    //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));
      }
    }
  }

  private List<RangeFacet> extractRangeFacets(NamedList<NamedList<Object>> rf) {
    List<RangeFacet> 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 if (rawGap instanceof String && values.get("start") instanceof Date) {
        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);
      } else {
        String gap = (String) rawGap;
        String start = (String) values.get("start");
        String end = (String) values.get("end");
        
        Number before = (Number) values.get("before");
        Number after = (Number) values.get("after");
        Number between = (Number) values.get("between");
        
        rangeFacet = new RangeFacet.Currency(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);
    }
    return facetRanges;
  }

  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> subPivots = null;
      Map<String,FieldStatsInfo> fieldStatsInfos = null;
      Map<String,Integer> queryCounts = null;
      List<RangeFacet> ranges = null;

      if (4 <= nl.size()) {
        for(int index = 3; index < nl.size(); index++) {
          final String key = nl.getName(index);
          final Object val = nl.getVal(index);
          switch (key) {

          case "pivot": {
            assert null != val : "Server sent back 'null' for sub pivots?";
            assert val instanceof List : "Server sent non-List for sub pivots?";

            subPivots = readPivots( (List<NamedList>) val );
            break;
          }
          case "stats": {
            assert null != val : "Server sent back 'null' for stats?";
            assert val instanceof NamedList : "Server sent non-NamedList for stats?";

            fieldStatsInfos = extractFieldStatsInfo((NamedList<Object>) val);
            break;
          }
          case "queries": {
            // Parse the queries
            queryCounts = new LinkedHashMap<>();
            NamedList<Integer> fq = (NamedList<Integer>) val;
            if (fq != null) {
              for( Map.Entry<String, Integer> entry : fq ) {
                queryCounts.put( entry.getKey(), entry.getValue() );
              }
            }
            break;
          }
          case "ranges": {
            ranges  = extractRangeFacets((NamedList<NamedList<Object>>) val);
            break;
          }
          default: 
            throw new RuntimeException( "unknown key in pivot: "+ key+ " ["+val+"]");

          }
        }
      }

      values.add( new PivotField( f, v, cnt, subPivots, fieldStatsInfos, queryCounts, ranges ) );
    }
    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, Object> getExplainMap() {
    return _explainMap;
  }

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

  /**
   *
   * @return map with each group value as key and the expanded documents that belong to the group as value.
   * There is no guarantee on the order of the keys obtained via an iterator.
   *
   */
  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 ClusteringResponse getClusteringResponse() {
    return _clusterResponse;
  }

  public NestableJsonFacet getJsonFacetingResponse() {
    if (_jsonFacetingInfo != null && _jsonFacetingResponse == null) extractJsonFacetingInfo(_jsonFacetingInfo);
    return _jsonFacetingResponse;
  }

  public SuggesterResponse getSuggesterResponse() {
    return _suggestResponse;
  }

  public TermsResponse getTermsResponse() {
    return _termsResponse;
  }

  public NamedList<SolrDocumentList> getMoreLikeThis() {
    return _moreLikeThisInfo;
  }
  
  /**
   * 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 solrClient == null ?
      new DocumentObjectBinder().getBeans(type,_results):
      solrClient.getBinder().getBeans(type, _results);
  }

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

  public String getNextCursorMark() {
    return _cursorMarkNext;
  }
}



