/**
 *
 */
package org.eclipse.smila.solr.search;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.SolrResponse;
import org.apache.solr.client.solrj.response.FacetField;
import org.apache.solr.client.solrj.response.FieldStatsInfo;
import org.apache.solr.client.solrj.response.Group;
import org.apache.solr.client.solrj.response.GroupCommand;
import org.apache.solr.client.solrj.response.GroupResponse;
import org.apache.solr.client.solrj.response.IntervalFacet;
import org.apache.solr.client.solrj.response.PivotField;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.RangeFacet;
import org.apache.solr.client.solrj.response.SolrResponseBase;
import org.apache.solr.client.solrj.response.SpellCheckResponse;
import org.apache.solr.client.solrj.response.SpellCheckResponse.Collation;
import org.apache.solr.client.solrj.response.SpellCheckResponse.Correction;
import org.apache.solr.client.solrj.response.SpellCheckResponse.Suggestion;
import org.apache.solr.client.solrj.response.TermsResponse;
import org.apache.solr.client.solrj.response.TermsResponse.Term;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.util.NamedList;
import org.eclipse.smila.datamodel.Any;
import org.eclipse.smila.datamodel.Any.ValueType;
import org.eclipse.smila.datamodel.AnyMap;
import org.eclipse.smila.datamodel.AnySeq;
import org.eclipse.smila.datamodel.DataFactory;
import org.eclipse.smila.datamodel.Record;
import org.eclipse.smila.datamodel.Value;
import org.eclipse.smila.datamodel.util.AnyUtil;
import org.eclipse.smila.search.api.helper.ResultBuilder;
import org.eclipse.smila.solr.SolrConfig;
import org.eclipse.smila.solr.SolrConstants;
import org.eclipse.smila.solr.SolrUtils;
import org.eclipse.smila.solr.administration.FieldInfoCache;
import org.eclipse.smila.solr.params.SolrParams;

/**
 * @author pwissel
 *
 */
public class ResponseParser extends ResultBuilder {

  private final Log _log = LogFactory.getLog(getClass());

  private final DataFactory _factory = DataFactory.DEFAULT;

  private final SolrConfig _config;

  private final String _index;

  public ResponseParser(final Record record, final SolrConfig config, String index) {
    super(record);
    _config = config;
    _index = index;
  }

  public Record toRecord(final SolrResponse response) {
    if (response instanceof SolrResponseBase) {
      parseResponseBase((SolrResponseBase) response);
    }
    if (response instanceof QueryResponse) {
      parseQueryResponse((QueryResponse) response);
    }
    return this.getResult();
  }

  public Any toAny(final SolrResponse response) {
    return toRecord(response).getMetadata();
  }

  private AnyMap getResponseMap() {
    return _result.getMetadata().getMap(SolrParams.SOLR_PARAMETER_ATTRIBUTE, true).getMap(ResponseAccessor.RESPONSE,
      true);
  }

  @SuppressWarnings("unchecked")
  void parseResponseBase(final SolrResponseBase response) {
    final NamedList<Object> header = response.getResponseHeader();
    if (header != null) {
      final AnyMap responseHeader = getResponseMap().getMap(SolrConstants.RESPONSE_HEADER, true);
      SolrUtils.parseNamedList(header, responseHeader);
    }
  }

  void parseQueryResponse(final QueryResponse response) {
    parseResults(response);
    parseFacets(response);
    parseGrouping(response);
    parseTerms(response);
    parseSpellcheck(response);
    parseMoreLikeThis(response);
    parseCursorMark(response);
    parseDebug(response);
    parseStats(response);
    parseSuggest(response);
  }

  void parseResults(final QueryResponse response) {
    final SolrDocumentList documents = response.getResults();
    if (documents == null) {
      return;
    }
    // add general result fields
    final long numFound = documents.getNumFound();
    setCount(numFound);
    final Float maxScore = documents.getMaxScore();
    if (maxScore != null) {
      getResponseMap().put(SolrConstants.MAX_SCORE, maxScore);
    }
    // add document result fields
    for (final SolrDocument document : documents) {
      final AnyMap item = createResultItem(document);
      getResultRecords().add(item);
      // add highlighting
      parseHighlighting(response, item);
    }
  }

  private AnyMap createResultItem(final SolrDocument document) {
    final AnyMap item = getResultRecords().getFactory().createAnyMap();
    // add result fields to item
    for (final Entry<String, Object> entry : document.entrySet()) {
      final String key = entry.getKey();
      final Object value = entry.getValue();
      if (value == null) {
        continue;
      }
      if (value instanceof Collection) {
        addMultiKeyValuePairToItem(item, key, value);
      } else {
        addKeyValuePairToItem(item, key, value);
      }
    }
    return item;
  }

  private void addKeyValuePairToItem(final AnyMap item, final String key, final Object value) {
    final DataFactory factory = item.getFactory();
    final Value autoConvertedValue = factory.autoConvertValue(value);
    item.put(key, autoConvertedValue);
  }

  private void addMultiKeyValuePairToItem(final AnyMap item, final String key, final Object value) {
    final DataFactory factory = item.getFactory();
    final Collection<?> multiValues = (Collection<?>) value;
    for (final Object multiValue : multiValues) {
      final Value autoConvertedValue = factory.autoConvertValue(multiValue);
      item.add(key, autoConvertedValue);
    }
  }

  private void parseHighlighting(final QueryResponse response, final AnyMap item) {
    final Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
    if (highlighting == null) {
      return;
    }
    final String id = item.getStringValue(_config.getIdField(_index));
    if (id != null) {
      for (final Entry<String, List<String>> entry : highlighting.get(id).entrySet()) {
        final String attribute = entry.getKey();
        final List<String> text = entry.getValue();
        if (text.size() > 1) {
          addHighlightText(item, attribute, text);
        } else {
          addHighlightText(item, attribute, text.get(0));
        }
      }
    }
  }

  @SuppressWarnings("rawtypes")
  void parseFacets(final QueryResponse response) {
    final boolean fetchFacetFieldType = _config.isFetchFacetFieldType();
    // facet fields
    final List<FacetField> fieldFacets = response.getFacetFields();
    if (fieldFacets != null) {
      addFacetFields(fieldFacets, fetchFacetFieldType);
    }
    final List<RangeFacet> rangeFacets = response.getFacetRanges();
    if (rangeFacets != null) {
      addFacetRanges(rangeFacets);
    }
    final Map<String, Integer> queryFacets = response.getFacetQuery();
    if (queryFacets != null) {
      addFacetQueries(queryFacets);
    }
    final NamedList<List<PivotField>> pivotFacets = response.getFacetPivot();
    if (pivotFacets != null) {
      addFacetPivots(pivotFacets);
    }
    final List<IntervalFacet> intervalFacets = response.getIntervalFacets();
    if (intervalFacets != null) {
      addFacetIntervals(intervalFacets);
    }
  }

  private void addFacetFields(final List<FacetField> fieldFacets, final boolean fetchFacetFieldType) {
    for (FacetField facetField : fieldFacets) {
      // create facet
      final String fieldName = facetField.getName();
      final AnySeq facet = addFacet(fieldName);
      // fetch field type
      final ValueType valueType = getFacetFieldType(fieldName);
      // add facet values
      for (final org.apache.solr.client.solrj.response.FacetField.Count countObj : facetField.getValues()) {
        final String value = countObj.getName();
        final long count = countObj.getCount();
        addTypedFacetValue(facet, value, valueType, count);
      }
    }
  }

  @SuppressWarnings("rawtypes")
  private void addFacetRanges(final List<RangeFacet> rangeFacets) {
    for (final RangeFacet rangeFacet : rangeFacets) {
      // create facet
      final String fieldName = rangeFacet.getName();
      final AnySeq facet = addFacet(fieldName);
      // fetch field type
      final ValueType valueType = getFacetFieldType(fieldName);
      // add facet values
      for (final Object obj : rangeFacet.getCounts()) {
        final org.apache.solr.client.solrj.response.RangeFacet.Count countObj =
          (org.apache.solr.client.solrj.response.RangeFacet.Count) obj;
        final String value = countObj.getValue();
        final long count = countObj.getCount();
        addTypedFacetValue(facet, value, valueType, count);
      }
    }
  }

  private void addFacetQueries(final Map<String, Integer> queryFacets) {
    final AnySeq facet = addFacet(SolrConstants.QUERIES);
    for (final String query : queryFacets.keySet()) {
      final String value = query;
      final long count = new Long(queryFacets.get(query));
      addFacetValue(facet, value, count);
    }
  }

  private void addFacetPivots(final NamedList<List<PivotField>> pivotFacets) {
    final AnyMap pivot = getResponseMap().getMap(SolrConstants.FACET_PIVOT, true);
    SolrUtils.parseNamedList(pivotFacets, pivot);
  }

  private void addFacetIntervals(final List<IntervalFacet> intervalFacets) {
    for (final IntervalFacet intervalFacet : intervalFacets) {
      // create facet
      final String fieldName = intervalFacet.getField();
      final AnySeq facet = addFacet(fieldName);
      // add facet values
      for (final org.apache.solr.client.solrj.response.IntervalFacet.Count countObj : intervalFacet
        .getIntervals()) {
        final String value = countObj.getKey();
        final long count = countObj.getCount();
        addFacetValue(facet, value, count);
      }
    }
  }

  private ValueType getFacetFieldType(final String fieldName) {
    if (_config.isFetchFacetFieldType()) {
      try {
        return FieldInfoCache.getFieldInfo(_index, fieldName).getTypeAsValueType();
      } catch (InterruptedException | IOException exception) {
        if (_log.isWarnEnabled()) {
          final String message = String.format("Error getting value type for fieldName: %s.", fieldName);
          _log.warn(message, exception);
        }
      }
    }
    return null;
  }

  private void addTypedFacetValue(final AnySeq facet, final String value, final ValueType valueType,
    final long count) {
    if (valueType != null) {
      addFacetValue(facet, value, valueType, count);
    } else {
      final Value val = _factory.autoConvertValue(value);
      addFacetValue(facet, val, count);
    }
  }

  void parseGrouping(final QueryResponse response) {
    final GroupResponse groupResponse = response.getGroupResponse();
    if (groupResponse == null) {
      return;
    }
    for (final GroupCommand command : groupResponse.getValues()) {
      final String name = command.getName();
      final int matches = command.getMatches();
      final AnySeq group = addGroup(name, new Long(matches));
      // Add ngroups if not null
      final Integer ngroups = command.getNGroups();
      if (ngroups != null) {
        getGroups().put(SolrConstants.NGROUPS, ngroups);
      }
      final DataFactory factory = group.getFactory();
      for (Group solrGroup : command.getValues()) {
        // get group value and check for null
        String groupValue = solrGroup.getGroupValue();
        if (groupValue == null) {
          // skip group value if 'processNullGroupValue ' is not configured
          if (!_config.isProcessGroupValueNull()) {
            continue;
          }
          // otherwise get 'nullGroupValue' or use default <null>
          groupValue = _config.getGroupValueNull();
        }
        final Value value = factory.autoConvertValue(groupValue);
        final SolrDocumentList documents = solrGroup.getResult();
        final Long count = documents.getNumFound();
        final AnySeq results = factory.createAnySeq();
        for (final SolrDocument document : documents) {
          final AnyMap result = createResultItem(document);
          parseHighlighting(response, result);
          results.add(result);
        }
        addGroupResults(group, value, count, results);
      }
    }
  }

  void parseTerms(final QueryResponse response) {
    final TermsResponse termsResponse = response.getTermsResponse();
    if (termsResponse == null) {
      return;
    }
    // _solr/response/terms
    final AnyMap terms = getResponseMap().getMap(SolrConstants.TERMS, true);
    final Map<String, List<Term>> termMap = termsResponse.getTermMap();
    for (final Entry<String, List<Term>> entry : termMap.entrySet()) {
      final AnyMap field = terms.getMap(entry.getKey(), true);
      for (final Term term : entry.getValue()) {
        field.put(term.getTerm(), term.getFrequency());
      }
    }
  }

  void parseSpellcheck(final QueryResponse response) {
    final SpellCheckResponse spellcheckResponse = response.getSpellCheckResponse();
    if (spellcheckResponse == null) {
      return;
    }
    // _solr/response/spellcheck
    final AnyMap spellcheck = getResponseMap().getMap(SolrConstants.SPELLCHECK, true);
    // suggestions
    final Map<String, Suggestion> suggestionMap = spellcheckResponse.getSuggestionMap();
    if (!MapUtils.isEmpty(suggestionMap)) {
      final AnyMap suggestions = spellcheck.getMap(SolrConstants.SUGGESTIONS, true);
      for (final Entry<String, Suggestion> entry : suggestionMap.entrySet()) {
        final String name = entry.getKey();
        final Suggestion suggestion = entry.getValue();
        if (suggestion != null) {
          final AnyMap map = suggestions.getMap(name, true);
          map.put(SolrConstants.NUM_FOUND, suggestion.getNumFound());
          map.put(SolrConstants.START_OFFSET, suggestion.getStartOffset());
          map.put(SolrConstants.END_OFFSET, suggestion.getEndOffset());
          map.put(SolrConstants.ORIG_FREQ, suggestion.getOriginalFrequency());
          final List<String> alternatives = suggestion.getAlternatives();
          final List<Integer> alternativeFrequencies = suggestion.getAlternativeFrequencies();
          if (alternativeFrequencies == null) {
            map.put(SolrConstants.SUGGESTION, AnyUtil.objectToAny(alternatives));
          } else {
            final AnySeq extendedResults = map.getSeq(SolrConstants.SUGGESTION, true);
            final DataFactory factory = extendedResults.getFactory();
            int index = 0;
            for (final String word : alternatives) {
              final AnyMap extended = factory.createAnyMap();
              extended.put(SolrConstants.WORD, word);
              extended.put(SolrConstants.FREQ, alternativeFrequencies.get(index));
              extendedResults.add(extended);
              index++;
            }
          }
        }
      }
    }
    // extended collation
    final List<Collation> collationList = spellcheckResponse.getCollatedResults();
    if (!CollectionUtils.isEmpty(collationList)) {
      final AnySeq collations = spellcheck.getSeq(SolrConstants.COLLATIONS, true);
      final DataFactory factory = collations.getFactory();
      for (final Collation collationObj : collationList) {
        if (collationObj != null) {
          final AnyMap collation = factory.createAnyMap();
          collation.put(SolrConstants.COLLATION_QUERY, collationObj.getCollationQueryString());
          collation.put(SolrConstants.HITS, collationObj.getNumberOfHits());
          if (!CollectionUtils.isEmpty(collationObj.getMisspellingsAndCorrections())) {
            final AnyMap misspellingsAndCorrection =
              collation.getMap(SolrConstants.MISSPELLINGS_AND_CORRECTIONS, true);
            for (final Correction correction : collationObj.getMisspellingsAndCorrections()) {
              misspellingsAndCorrection.put(correction.getOriginal(), correction.getCorrection());
            }
          }
          collations.add(collation);
        }
      }
    }
  }

  @SuppressWarnings("unchecked")
  void parseMoreLikeThis(final QueryResponse response) {
    final Object moreLikeThisObj = response.getResponse().get(SolrConstants.MORE_LIKE_THIS);
    if (moreLikeThisObj != null) {
      final AnyMap moreLikeThis = getResponseMap().getMap(SolrConstants.MORE_LIKE_THIS, true);
      final NamedList<SolrDocumentList> relatedDocuments = (NamedList<SolrDocumentList>) moreLikeThisObj;
      final Iterator<Entry<String, SolrDocumentList>> iterator = relatedDocuments.iterator();
      while (iterator.hasNext()) {
        final Entry<String, SolrDocumentList> entry = iterator.next();
        final String name = entry.getKey();
        final AnyMap result = moreLikeThis.getMap(name, true);
        final SolrDocumentList documents = entry.getValue();
        result.put(SolrConstants.NUM_FOUND, documents.getNumFound());
        result.put(SolrConstants.START, documents.getStart());
        final Float maxScore = documents.getMaxScore();
        if (maxScore != null) {
          result.put(SolrConstants.MAX_SCORE, maxScore);
        }
        for (final SolrDocument document : documents) {
          final AnyMap item = createResultItem(document);
          result.add(SolrConstants.RELATED, item);
        }
      }
    }
  }

  void parseCursorMark(final QueryResponse response) {
    final String nextCursorMark = response.getNextCursorMark();
    if (!StringUtils.isEmpty(nextCursorMark)) {
      getResponseMap().put(SolrConstants.NEXT_CURSOR_MARK, nextCursorMark);
    }
  }

  void parseDebug(final QueryResponse response) {
    final Map<String, Object> debugMap = response.getDebugMap();
    if (debugMap != null) {
      final AnyMap debug = getResponseMap().getMap(SolrConstants.DEBUG, true);
      for (final Entry<String, Object> entry : debugMap.entrySet()) {
        final String name = entry.getKey();
        final Object object = entry.getValue();
        if (object instanceof NamedList<?>) {
          SolrUtils.parseNamedList((NamedList<?>) object, debug.getMap(name, true));
        } else {
          final Value value = debug.getFactory().autoConvertValue(object);
          debug.put(name, value);
        }
      }
    }
  }

  void parseStats(final QueryResponse response) {
    final Map<String, FieldStatsInfo> fieldStatsInfoMap = response.getFieldStatsInfo();
    if (fieldStatsInfoMap != null) {
      final AnyMap stats = getResponseMap().getMap(SolrConstants.STATS, true);
      final DataFactory factory = stats.getFactory();
      for (final Entry<String, FieldStatsInfo> statsEntry : fieldStatsInfoMap.entrySet()) {
        final AnyMap field = stats.getMap(statsEntry.getKey(), true);
        final FieldStatsInfo fieldStatsInfo = statsEntry.getValue();
        addStats(field, fieldStatsInfo, factory);
        // facets
        final Map<String, List<FieldStatsInfo>> facetInfo = fieldStatsInfo.getFacets();
        if (facetInfo != null) {
          final AnyMap facets = field.getMap(SolrConstants.FACETS, true);
          for (final Entry<String, List<FieldStatsInfo>> facetsEntry : facetInfo.entrySet()) {
            final AnyMap facet = facets.getMap(facetsEntry.getKey(), true);
            for (final FieldStatsInfo facetStatsInfo : facetsEntry.getValue()) {
              addStats(facet, facetStatsInfo, factory);
            }
          }
        }
      }
    }
  }

  private void addStats(final AnyMap stats, final FieldStatsInfo fieldStatsInfo, final DataFactory factory) {
    stats.put(SolrConstants.MIN, factory.autoConvertValue(fieldStatsInfo.getMin()));
    stats.put(SolrConstants.MAX, factory.autoConvertValue(fieldStatsInfo.getMax()));
    stats.put(SolrConstants.COUNT, fieldStatsInfo.getCount());
    stats.put(SolrConstants.MISSING, fieldStatsInfo.getMissing());
    stats.put(SolrConstants.SUM, factory.autoConvertValue(fieldStatsInfo.getSum()));
    stats.put(SolrConstants.MEAN, factory.autoConvertValue(fieldStatsInfo.getMean()));
    stats.put(SolrConstants.STDDEV, fieldStatsInfo.getStddev());
  }

  @SuppressWarnings("unchecked")
  void parseSuggest(final QueryResponse response) {
    final Object obj = response.getResponse().get(SolrConstants.SUGGEST);
    if (obj != null) {
      final AnyMap suggest = getResponseMap().getMap(SolrConstants.SUGGEST, true);
      if (obj instanceof Map<?, ?>) {
        final Map<Object, Object> dictionaries = (Map<Object, Object>) obj;
        for (final Entry<Object, Object> dictionary : dictionaries.entrySet()) {
          final String name = (String) dictionary.getKey();
          final Object list = dictionary.getValue();
          if (list instanceof NamedList<?>) {
            final AnyMap target = suggest.getMap(name, true);
            SolrUtils.parseNamedList((NamedList<?>) list, target);
          }
        }
      }
    }
  }

}
