/*
 * 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.search;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.carrotsearch.hppc.FloatArrayList;
import com.carrotsearch.hppc.IntArrayList;
import com.carrotsearch.hppc.IntIntHashMap;
import com.carrotsearch.hppc.IntLongHashMap;
import com.carrotsearch.hppc.cursors.IntIntCursor;
import com.carrotsearch.hppc.cursors.IntLongCursor;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.codecs.DocValuesProducer;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.EmptyDocValuesProducer;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.FieldInfos;
import org.apache.lucene.index.FilterLeafReader;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.MultiDocValues;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.index.OrdinalMap;
import org.apache.lucene.index.SortedDocValues;
import org.apache.lucene.queries.function.FunctionQuery;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.LeafFieldComparator;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.QueryVisitor;
import org.apache.lucene.search.Scorable;
import org.apache.lucene.search.ScoreMode;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.BitSetIterator;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.LongValues;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.GroupParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.handler.component.QueryElevationComponent;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestInfo;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.NumberType;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.StrField;
import org.apache.solr.uninverting.UninvertingReader;
import org.apache.solr.util.IntFloatDynamicMap;
import org.apache.solr.util.IntIntDynamicMap;
import org.apache.solr.util.IntLongDynamicMap;

import static org.apache.solr.common.params.CommonParams.SORT;

/**

 The <b>CollapsingQParserPlugin</b> is a PostFilter that performs field collapsing.
 This is a high performance alternative to standard Solr
 field collapsing (with ngroups) when the number of distinct groups
 in the result set is high.
 <p>
 Sample syntax:
 <p>
 Collapse based on the highest scoring document:
 <p>

 fq=(!collapse field=field_name}

 <p>
 Collapse based on the min value of a numeric field:
 <p>
 fq={!collapse field=field_name min=field_name}
 <p>
 Collapse based on the max value of a numeric field:
 <p>
 fq={!collapse field=field_name max=field_name}
 <p>
 Collapse with a null policy:
 <p>
 fq={!collapse field=field_name nullPolicy=nullPolicy}
 <p>
 There are three null policies: <br>
 ignore : removes docs with a null value in the collapse field (default).<br>
 expand : treats each doc with a null value in the collapse field as a separate group.<br>
 collapse : collapses all docs with a null value into a single group using either highest score, or min/max.
 <p>
 The CollapsingQParserPlugin fully supports the QueryElevationComponent
 **/

public class CollapsingQParserPlugin extends QParserPlugin {

  public static final String NAME = "collapse";
  public static final String NULL_COLLAPSE = "collapse";
  public static final String NULL_IGNORE = "ignore";
  public static final String NULL_EXPAND = "expand";
  public static final String HINT_TOP_FC = "top_fc";
  public static final String HINT_MULTI_DOCVALUES = "multi_docvalues";


  public QParser createParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest request) {
    return new CollapsingQParser(qstr, localParams, params, request);
  }

  private static class CollapsingQParser extends QParser {

    public CollapsingQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest request) {
      super(qstr, localParams, params, request);
    }

    public Query parse() throws SyntaxError {
      try {
        return new CollapsingPostFilter(localParams, params, req);
      } catch (Exception e) {
        throw new SyntaxError(e.getMessage(), e);
      }
    }
  }

  public static enum GroupHeadSelectorType {
    MIN, MAX, SORT, SCORE;
    public static EnumSet<GroupHeadSelectorType> MIN_MAX = EnumSet.of(MIN, MAX);
  }

  /**
   * Models all the information about how group head documents should be selected
   */
  public static final class GroupHeadSelector {

    /**
     * The param value for this selector whose meaning depends on type.
     * (ie: a field or valuesource for MIN/MAX, a sort string for SORT, "score" for SCORE).
     * Will never be null.
     */
    public final String selectorText;
    /** The type for this selector, will never be null */
    public final GroupHeadSelectorType type;
    private GroupHeadSelector(String s, GroupHeadSelectorType type) {
      assert null != s;
      assert null != type;

      this.selectorText = s;
      this.type = type;
    }

    @Override
    public boolean equals(final Object other) {
      if (other instanceof GroupHeadSelector) {
        final GroupHeadSelector that = (GroupHeadSelector) other;
        return (this.type == that.type) && this.selectorText.equals(that.selectorText);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return 17 * (31 + selectorText.hashCode()) * (31 + type.hashCode());
    }

    /**
     * returns a new GroupHeadSelector based on the specified local params
     */
    public static GroupHeadSelector build(final SolrParams localParams) {
      final String sortString = StringUtils.defaultIfBlank(localParams.get(SORT), null);
      final String max = StringUtils.defaultIfBlank(localParams.get("max"), null);
      final String min = StringUtils.defaultIfBlank(localParams.get("min"), null);

      if (1 < numNotNull(min, max, sortString)) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
                                "At most one localparam for selecting documents (min, max, sort) may be specified: " + localParams.toString());
      }

      if (null != sortString) {
        return new GroupHeadSelector(sortString, GroupHeadSelectorType.SORT);
      } else if (null != min) {
        return new GroupHeadSelector(min, GroupHeadSelectorType.MIN);
      } else if (null != max) {
        return new GroupHeadSelector(max, GroupHeadSelectorType.MAX);
      }
      // default
      return new GroupHeadSelector("score", GroupHeadSelectorType.SCORE);
    }
  }

  public static class CollapsingPostFilter extends ExtendedQueryBase implements PostFilter {

    private String collapseField;
    private final GroupHeadSelector groupHeadSelector;
    private final SortSpec sortSpec; // may be null, parsed at most once from groupHeadSelector
    public String hint;
    private boolean needsScores = true;
    private boolean needsScores4Collapsing = false;
    private int nullPolicy;
    private Set<BytesRef> boosted; // ordered by "priority"
    public static final int NULL_POLICY_IGNORE = 0;
    public static final int NULL_POLICY_COLLAPSE = 1;
    public static final int NULL_POLICY_EXPAND = 2;
    private int size;

    public String getField(){
      return this.collapseField;
    }

    public void setCache(boolean cache) {

    }

    public void setCacheSep(boolean cacheSep) {

    }

    public boolean getCacheSep() {
      return false;
    }

    public boolean getCache() {
      return false;
    }

    // Only a subset of fields in hashCode/equals?

    public int hashCode() {
      int hashCode = classHash();
      hashCode = 31 * hashCode + collapseField.hashCode();
      hashCode = 31 * hashCode + groupHeadSelector.hashCode();
      hashCode = 31 * hashCode + nullPolicy;
      return hashCode;
    }

    public boolean equals(Object other) {
      return sameClassAs(other) &&
             equalsTo(getClass().cast(other));
    }

    private boolean equalsTo(CollapsingPostFilter other) {
      return collapseField.equals(other.collapseField) &&
             groupHeadSelector.equals(other.groupHeadSelector) &&
             nullPolicy == other.nullPolicy;
    }

    @Override
    public void visit(QueryVisitor visitor) {
      visitor.visitLeaf(this);
    }

    public int getCost() {
      return Math.max(super.getCost(), 100);
    }

    public String toString(String s) {
      return s;
    }

    public CollapsingPostFilter(SolrParams localParams, SolrParams params, SolrQueryRequest request) {
      // Don't allow collapsing if grouping is being used.
      if (request.getParams().getBool(GroupParams.GROUP, false)) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can not use collapse with Grouping enabled");
      }

      this.collapseField = localParams.get("field");
      if (this.collapseField == null) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Required 'field' param is missing.");
      }

      // if unknown field, this would fail fast
      SchemaField collapseFieldSf = request.getSchema().getField(this.collapseField);
      if (!(collapseFieldSf.isUninvertible() || collapseFieldSf.hasDocValues())) {
        // uninvertible=false and docvalues=false
        // field can't be indexed=false and uninvertible=true
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Collapsing field '" + collapseField +
            "' should be either docValues enabled or indexed with uninvertible enabled");
      } else if (collapseFieldSf.multiValued()) {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Collapsing not supported on multivalued fields");
      }

      this.groupHeadSelector = GroupHeadSelector.build(localParams);

      if (groupHeadSelector.type.equals(GroupHeadSelectorType.SORT) &&
          CollapseScore.wantsCScore(groupHeadSelector.selectorText)) {
        // we can't support Sorts that wrap functions that include "cscore()" because
        // the abstraction layer for Sort/SortField rewriting gives each clause it's own
        // context Map which we don't have access to -- so for now, give a useful error
        // (as early as possible) if attempted
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
                                "Using cscore() as a function in the 'sort' local "+
                                "param of the collapse parser is not supported");
      }



      this.sortSpec = GroupHeadSelectorType.SORT.equals(groupHeadSelector.type)
        ? SortSpecParsing.parseSortSpec(groupHeadSelector.selectorText, request)
        : null;

      this.hint = localParams.get("hint");
      this.size = localParams.getInt("size", 100000); //Only used for collapsing on int fields.

      {
        final SolrRequestInfo info = SolrRequestInfo.getRequestInfo();
        assert null != info;

        // may be null in some esoteric corner usages
        final ResponseBuilder rb = info.getResponseBuilder();
        final SortSpec topSort = null == rb ? null : rb.getSortSpec();

        this.needsScores4Collapsing = GroupHeadSelectorType.SCORE.equals(groupHeadSelector.type) ||
            (GroupHeadSelectorType.SORT.equals(groupHeadSelector.type)
                && this.sortSpec.includesScore()) ||
            (GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type)
                && CollapseScore.wantsCScore(groupHeadSelector.selectorText));
        this.needsScores = needsScores4Collapsing ||
          (info.getRsp().getReturnFields().wantsScore() ||
           (null != topSort && topSort.includesScore()) ||
           (this.boosted != null));

        if (this.needsScores && null != rb) {
          // regardless of why we need scores ensure the IndexSearcher will compute them
          // for the "real" docs.  (ie: maybe we need them because we were
          // asked to compute them for the collapsed docs, maybe we need them because in
          // order to find the groupHead we need them computed for us.

          rb.setFieldFlags( rb.getFieldFlags() | SolrIndexSearcher.GET_SCORES);
        }
      }

      String nPolicy = localParams.get("nullPolicy", NULL_IGNORE);
      if(nPolicy.equals(NULL_IGNORE)) {
        this.nullPolicy = NULL_POLICY_IGNORE;
      } else if (nPolicy.equals(NULL_COLLAPSE)) {
        this.nullPolicy = NULL_POLICY_COLLAPSE;
      } else if(nPolicy.equals((NULL_EXPAND))) {
        this.nullPolicy = NULL_POLICY_EXPAND;
      } else {
        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Invalid nullPolicy:"+nPolicy);
      }
    }

    @SuppressWarnings({"unchecked"})
    public DelegatingCollector getFilterCollector(IndexSearcher indexSearcher) {
      try {

        SolrIndexSearcher searcher = (SolrIndexSearcher)indexSearcher;
        CollectorFactory collectorFactory = new CollectorFactory();
        //Deal with boosted docs.
        //We have to deal with it here rather then the constructor because
        //because the QueryElevationComponent runs after the Queries are constructed.

        IntIntHashMap boostDocsMap = null;
        @SuppressWarnings({"rawtypes"})
        Map context = null;
        SolrRequestInfo info = SolrRequestInfo.getRequestInfo();
        if(info != null) {
          context = info.getReq().getContext();
        }

        if(this.boosted == null && context != null) {
          this.boosted = (Set<BytesRef>)context.get(QueryElevationComponent.BOOSTED);
        }

        boostDocsMap = QueryElevationComponent.getBoostDocs(searcher, this.boosted, context);
        return collectorFactory.getCollector(this.collapseField,
                                             this.groupHeadSelector,
                                             this.sortSpec,
                                             this.nullPolicy,
                                             this.hint,
                                             this.needsScores4Collapsing,
                                             this.needsScores,
                                             this.size,
                                             boostDocsMap,
                                             searcher);

      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }

  }

  /**
   * This forces the use of the top level field cache for String fields.
   * This is VERY fast at query time but slower to warm and causes insanity.
   */
  public static LeafReader getTopFieldCacheReader(SolrIndexSearcher searcher, String collapseField) {
    UninvertingReader.Type type = null;
    final SchemaField f = searcher.getSchema().getFieldOrNull(collapseField);
    assert null != f;        // should already be enforced higher up
    assert !f.multiValued(); // should already be enforced higher up

    assert f.getType() instanceof StrField; // this method shouldn't be called otherwise
    if (f.indexed() && f.isUninvertible()) {
      type = UninvertingReader.Type.SORTED;
    }

    return UninvertingReader.wrap(
        new ReaderWrapper(searcher.getSlowAtomicReader(), collapseField),
        Collections.singletonMap(collapseField, type)::get);
  }

  private static class ReaderWrapper extends FilterLeafReader {

    private final FieldInfos fieldInfos;

    ReaderWrapper(LeafReader leafReader, String field) {
      super(leafReader);

      // TODO can we just do "field" and not bother with the other fields?
      List<FieldInfo> newInfos = new ArrayList<>(in.getFieldInfos().size());
      for (FieldInfo fieldInfo : in.getFieldInfos()) {
        if (fieldInfo.name.equals(field)) {
          FieldInfo f = new FieldInfo(fieldInfo.name,
              fieldInfo.number,
              fieldInfo.hasVectors(),
              fieldInfo.hasNorms(),
              fieldInfo.hasPayloads(),
              fieldInfo.getIndexOptions(),
              DocValuesType.NONE,
              fieldInfo.getDocValuesGen(),
              fieldInfo.attributes(),
              fieldInfo.getPointDimensionCount(),
              fieldInfo.getPointIndexDimensionCount(),
              fieldInfo.getPointNumBytes(),
              fieldInfo.isSoftDeletesField());
          newInfos.add(f);
        } else {
          newInfos.add(fieldInfo);
        }
      }
      FieldInfos infos = new FieldInfos(newInfos.toArray(new FieldInfo[newInfos.size()]));
      this.fieldInfos = infos;
    }

    public FieldInfos getFieldInfos() {
      return fieldInfos;
    }

    public SortedDocValues getSortedDocValues(String field) {
      return null;
    }

    // NOTE: delegating the caches is wrong here as we are altering the content
    // of the reader, this should ONLY be used under an uninvertingreader which
    // will restore doc values back using uninversion, otherwise all sorts of
    // crazy things could happen.

    @Override
    public CacheHelper getCoreCacheHelper() {
      return in.getCoreCacheHelper();
    }

    @Override
    public CacheHelper getReaderCacheHelper() {
      return in.getReaderCacheHelper();
    }
  }


  private static class ScoreAndDoc extends Scorable {

    public float score;
    public int docId;

    public float score() {
      return score;
    }

    public int docID() {
      return docId;
    }
  }



  /*
  * Collapses on Ordinal Values using Score to select the group head.
  */

  private static class OrdScoreCollector extends DelegatingCollector {

    private LeafReaderContext[] contexts;
    private final DocValuesProducer collapseValuesProducer;
    private FixedBitSet collapsedSet;
    private SortedDocValues collapseValues;
    private OrdinalMap ordinalMap;
    private SortedDocValues segmentValues;
    private LongValues segmentOrdinalMap;
    private MultiDocValues.MultiSortedDocValues multiSortedDocValues;
    private IntIntDynamicMap ords;
    private IntFloatDynamicMap scores;
    private int maxDoc;
    private int nullPolicy;
    private float nullScore = -Float.MAX_VALUE;
    private int nullDoc;
    private FloatArrayList nullScores;
    private IntArrayList boostOrds;
    private IntArrayList boostDocs;
    private MergeBoost mergeBoost;
    private boolean boosts;

    public OrdScoreCollector(int maxDoc,
                             int segments,
                             DocValuesProducer collapseValuesProducer,
                             int nullPolicy,
                             IntIntHashMap boostDocsMap,
                             IndexSearcher searcher) throws IOException {
      this.maxDoc = maxDoc;
      this.contexts = new LeafReaderContext[segments];
      List<LeafReaderContext> con = searcher.getTopReaderContext().leaves();
      for(int i=0; i<con.size(); i++) {
        contexts[i] = con.get(i);
      }

      this.collapsedSet = new FixedBitSet(maxDoc);
      this.collapseValuesProducer = collapseValuesProducer;
      this.collapseValues = collapseValuesProducer.getSorted(null);

      int valueCount = collapseValues.getValueCount();
      if(collapseValues instanceof MultiDocValues.MultiSortedDocValues) {
        this.multiSortedDocValues = (MultiDocValues.MultiSortedDocValues)collapseValues;
        this.ordinalMap = multiSortedDocValues.mapping;
      }
      this.ords = new IntIntDynamicMap(valueCount, -1);
      this.scores = new IntFloatDynamicMap(valueCount, -Float.MAX_VALUE);
      this.nullPolicy = nullPolicy;
      if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        nullScores = new FloatArrayList();
      }

      if(boostDocsMap != null) {
        this.boosts = true;
        this.boostOrds = new IntArrayList();
        this.boostDocs = new IntArrayList();
        int[] bd = new int[boostDocsMap.size()];
        Iterator<IntIntCursor> it =  boostDocsMap.iterator();
        int index = -1;
        while(it.hasNext()) {
          IntIntCursor cursor = it.next();
          bd[++index] = cursor.key;
        }

        Arrays.sort(bd);
        this.mergeBoost = new MergeBoost(bd);
      }
    }

    @Override public ScoreMode scoreMode() { return ScoreMode.COMPLETE; }

    @Override
    protected void doSetNextReader(LeafReaderContext context) throws IOException {
      this.contexts[context.ord] = context;
      this.docBase = context.docBase;
      if(ordinalMap != null) {
        this.segmentValues = this.multiSortedDocValues.values[context.ord];
        this.segmentOrdinalMap = ordinalMap.getGlobalOrds(context.ord);
      } else {
        this.segmentValues = collapseValues;
      }
    }

    @Override
    public void collect(int contextDoc) throws IOException {
      int globalDoc = contextDoc+this.docBase;
      int ord = -1;
      if(this.ordinalMap != null) {
        //Handle ordinalMapping case
        if (segmentValues.advanceExact(contextDoc)) {
          ord = (int)segmentOrdinalMap.get(segmentValues.ordValue());
        } else {
          ord = -1;
        }
      } else {
        //Handle top Level FieldCache or Single Segment Case
        if (segmentValues.advanceExact(globalDoc)) {
          ord = segmentValues.ordValue();
        } else {
          ord = -1;
        }
      }

      // Check to see if we have documents boosted by the QueryElevationComponent
      if(boosts && mergeBoost.boost(globalDoc)) {
        boostDocs.add(globalDoc);
        boostOrds.add(ord);
        return;
      }

      if(ord > -1) {
        float score = scorer.score();
        if(score > scores.get(ord)) {
          ords.put(ord, globalDoc);
          scores.put(ord, score);
        }
      } else if(nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        float score = scorer.score();
        if(score > nullScore) {
          nullScore = score;
          nullDoc = globalDoc;
        }
      } else if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        collapsedSet.set(globalDoc);
        nullScores.add(scorer.score());
      }
    }

    @Override
    public void finish() throws IOException {
      if(contexts.length == 0) {
        return;
      }

      if(nullScore > 0) {
        collapsedSet.set(nullDoc);
      }

      //Handle the boosted docs.
      if(this.boostOrds != null) {
        int s = boostOrds.size();
        for(int i=0; i<s; i++) {
          int ord = this.boostOrds.get(i);
          if(ord > -1) {
            //Remove any group heads that are in the same groups as boosted documents.
            ords.remove(ord);
          }
          //Add the boosted docs to the collapsedSet
          this.collapsedSet.set(boostDocs.get(i));
        }
        mergeBoost.reset(); // Reset mergeBoost because we're going to use it again.
      }

      //Build the sorted DocSet of group heads.
      ords.forEachValue(doc -> collapsedSet.set(doc));

      int currentContext = 0;
      int currentDocBase = 0;

      collapseValues = collapseValuesProducer.getSorted(null);

      if(collapseValues instanceof MultiDocValues.MultiSortedDocValues) {
        this.multiSortedDocValues = (MultiDocValues.MultiSortedDocValues)collapseValues;
        this.ordinalMap = multiSortedDocValues.mapping;
      }

      if(ordinalMap != null) {
        this.segmentValues = this.multiSortedDocValues.values[currentContext];
        this.segmentOrdinalMap = this.ordinalMap.getGlobalOrds(currentContext);
      } else {
        this.segmentValues = collapseValues;
      }

      int nextDocBase = currentContext+1 < contexts.length ? contexts[currentContext+1].docBase : maxDoc;
      leafDelegate = delegate.getLeafCollector(contexts[currentContext]);
      ScoreAndDoc dummy = new ScoreAndDoc();
      leafDelegate.setScorer(dummy);
      DocIdSetIterator it = new BitSetIterator(collapsedSet, 0L); // cost is not useful here
      int docId = -1;
      int index = -1;
      while((docId = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
        while(docId >= nextDocBase) {
          currentContext++;
          currentDocBase = contexts[currentContext].docBase;
          nextDocBase = currentContext+1 < contexts.length ? contexts[currentContext+1].docBase : maxDoc;
          leafDelegate = delegate.getLeafCollector(contexts[currentContext]);
          leafDelegate.setScorer(dummy);
          if(ordinalMap != null) {
            this.segmentValues = this.multiSortedDocValues.values[currentContext];
            this.segmentOrdinalMap = this.ordinalMap.getGlobalOrds(currentContext);
          }
        }

        int contextDoc = docId-currentDocBase;

        int ord = -1;
        if(this.ordinalMap != null) {
          //Handle ordinalMapping case
          if (segmentValues.advanceExact(contextDoc)) {
            ord = (int)segmentOrdinalMap.get(segmentValues.ordValue());
          }
        } else {
          //Handle top Level FieldCache or Single Segment Case
          if (segmentValues.advanceExact(docId)) {
            ord = segmentValues.ordValue();
          }
        }

        if(ord > -1) {
          dummy.score = scores.get(ord);
        } else if(boosts && mergeBoost.boost(docId)) {
          //Ignore so it doesn't mess up the null scoring.
        } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
          dummy.score = nullScore;
        } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
          dummy.score = nullScores.get(++index);
        }

        dummy.docId = contextDoc;
        leafDelegate.collect(contextDoc);
      }

      if(delegate instanceof DelegatingCollector) {
        ((DelegatingCollector) delegate).finish();
      }
    }
  }

  /*
  * Collapses on an integer field using the score to select the group head.
  */

  private static class IntScoreCollector extends DelegatingCollector {

    private LeafReaderContext[] contexts;
    private FixedBitSet collapsedSet;
    private NumericDocValues collapseValues;
    private IntLongHashMap cmap;
    private int maxDoc;
    private int nullPolicy;
    private float nullScore = -Float.MAX_VALUE;
    private int nullDoc;
    private FloatArrayList nullScores;
    private IntArrayList boostKeys;
    private IntArrayList boostDocs;
    private MergeBoost mergeBoost;
    private boolean boosts;
    private String field;
    private int nullValue;

    public IntScoreCollector(int maxDoc,
                             int segments,
                             int nullValue,
                             int nullPolicy,
                             int size,
                             String field,
                             IntIntHashMap boostDocsMap,
                             IndexSearcher searcher) {
      this.maxDoc = maxDoc;
      this.contexts = new LeafReaderContext[segments];
      List<LeafReaderContext> con = searcher.getTopReaderContext().leaves();
      for(int i=0; i<con.size(); i++) {
        contexts[i] = con.get(i);
      }

      this.collapsedSet = new FixedBitSet(maxDoc);
      this.nullValue = nullValue;
      this.nullPolicy = nullPolicy;
      if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        nullScores = new FloatArrayList();
      }
      this.cmap = new IntLongHashMap(size);
      this.field = field;

      if(boostDocsMap != null) {
        this.boosts = true;
        this.boostDocs = new IntArrayList();
        this.boostKeys = new IntArrayList();
        int[] bd = new int[boostDocsMap.size()];
        Iterator<IntIntCursor> it =  boostDocsMap.iterator();
        int index = -1;
        while(it.hasNext()) {
          IntIntCursor cursor = it.next();
          bd[++index] = cursor.key;
        }

        Arrays.sort(bd);
        this.mergeBoost = new MergeBoost(bd);
        this.boosts = true;
      }

    }

    @Override public ScoreMode scoreMode() { return ScoreMode.COMPLETE; }

    @Override
    protected void doSetNextReader(LeafReaderContext context) throws IOException {
      this.contexts[context.ord] = context;
      this.docBase = context.docBase;
      this.collapseValues = DocValues.getNumeric(context.reader(), this.field);
    }

    @Override
    public void collect(int contextDoc) throws IOException {
      int collapseValue;
      if (collapseValues.advanceExact(contextDoc)) {
        collapseValue = (int) collapseValues.longValue();
      } else {
        collapseValue = 0;
      }
      int globalDoc = docBase+contextDoc;

      // Check to see of we have documents boosted by the QueryElevationComponent
      if(boosts && mergeBoost.boost(globalDoc)) {
        boostDocs.add(globalDoc);
        boostKeys.add(collapseValue);
        return;
      }

      if(collapseValue != nullValue) {
        float score = scorer.score();
        final int idx;
        if((idx = cmap.indexOf(collapseValue)) >= 0) {
          long scoreDoc = cmap.indexGet(idx);
          int testScore = (int)(scoreDoc>>32);
          int currentScore = Float.floatToRawIntBits(score);
          if(currentScore > testScore) {
            //Current score is higher so replace the old scoreDoc with the current scoreDoc
            cmap.indexReplace(idx, (((long)currentScore)<<32)+globalDoc);
          }
        } else {
          //Combine the score and document into a long.
          long scoreDoc = (((long)Float.floatToRawIntBits(score))<<32)+globalDoc;
          cmap.indexInsert(idx, collapseValue, scoreDoc);
        }
      } else if(nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        float score = scorer.score();
        if(score > this.nullScore) {
          this.nullScore = score;
          this.nullDoc = globalDoc;
        }
      } else if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        collapsedSet.set(globalDoc);
        nullScores.add(scorer.score());
      }
    }

    @Override
    public void finish() throws IOException {
      if(contexts.length == 0) {
        return;
      }

      if(nullScore > -1) {
        collapsedSet.set(nullDoc);
      }

      //Handle the boosted docs.
      if(this.boostKeys != null) {
        int s = boostKeys.size();
        for(int i=0; i<s; i++) {
          int key = this.boostKeys.get(i);
          if(key != nullValue) {
            cmap.remove(key);
          }
          //Add the boosted docs to the collapsedSet
          this.collapsedSet.set(boostDocs.get(i));
        }
      }

      Iterator<IntLongCursor> it1 = cmap.iterator();

      while(it1.hasNext()) {
        IntLongCursor cursor = it1.next();
        int doc = (int)cursor.value;
        collapsedSet.set(doc);
      }

      int currentContext = 0;
      int currentDocBase = 0;

      collapseValues = DocValues.getNumeric(contexts[currentContext].reader(), this.field);
      int nextDocBase = currentContext+1 < contexts.length ? contexts[currentContext+1].docBase : maxDoc;
      leafDelegate = delegate.getLeafCollector(contexts[currentContext]);
      ScoreAndDoc dummy = new ScoreAndDoc();
      leafDelegate.setScorer(dummy);
      DocIdSetIterator it = new BitSetIterator(collapsedSet, 0L); // cost is not useful here
      int globalDoc = -1;
      int nullScoreIndex = 0;
      while((globalDoc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {

        while(globalDoc >= nextDocBase) {
          currentContext++;
          currentDocBase = contexts[currentContext].docBase;
          nextDocBase = currentContext+1 < contexts.length ? contexts[currentContext+1].docBase : maxDoc;
          leafDelegate = delegate.getLeafCollector(contexts[currentContext]);
          leafDelegate.setScorer(dummy);
          collapseValues = DocValues.getNumeric(contexts[currentContext].reader(), this.field);
        }

        int contextDoc = globalDoc-currentDocBase;
        int collapseValue;
        if (collapseValues.advanceExact(contextDoc)) {
          collapseValue = (int) collapseValues.longValue();
        } else {
          collapseValue = 0;
        }

        if(collapseValue != nullValue) {
          long scoreDoc = cmap.get(collapseValue);
          dummy.score = Float.intBitsToFloat((int)(scoreDoc>>32));
        } else if(boosts && mergeBoost.boost(globalDoc)) {
          //Ignore so boosted documents don't mess up the null scoring policies.
        } else if (nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
          dummy.score = nullScore;
        } else if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
          dummy.score = nullScores.get(nullScoreIndex++);
        }

        dummy.docId = contextDoc;
        leafDelegate.collect(contextDoc);
      }

      if(delegate instanceof DelegatingCollector) {
        ((DelegatingCollector) delegate).finish();
      }
    }
  }

  /**
   * Collapse on Ordinal value field.
   */
  private static class OrdFieldValueCollector extends DelegatingCollector {
    private LeafReaderContext[] contexts;

    private DocValuesProducer collapseValuesProducer;
    private SortedDocValues collapseValues;
    protected OrdinalMap ordinalMap;
    protected SortedDocValues segmentValues;
    protected LongValues segmentOrdinalMap;
    protected MultiDocValues.MultiSortedDocValues multiSortedDocValues;

    private int maxDoc;
    private int nullPolicy;

    private OrdFieldValueStrategy collapseStrategy;
    private boolean needsScores4Collapsing;
    private boolean needsScores;

    public OrdFieldValueCollector(int maxDoc,
                                  int segments,
                                  DocValuesProducer collapseValuesProducer,
                                  int nullPolicy,
                                  GroupHeadSelector groupHeadSelector,
                                  SortSpec sortSpec,
                                  boolean needsScores4Collapsing,
                                  boolean needsScores,
                                  FieldType fieldType,
                                  IntIntHashMap boostDocs,
                                  FunctionQuery funcQuery, IndexSearcher searcher) throws IOException{

      assert ! GroupHeadSelectorType.SCORE.equals(groupHeadSelector.type);

      this.maxDoc = maxDoc;
      this.contexts = new LeafReaderContext[segments];
      List<LeafReaderContext> con = searcher.getTopReaderContext().leaves();
      for(int i=0; i<con.size(); i++) {
        contexts[i] = con.get(i);
      }
      this.collapseValuesProducer = collapseValuesProducer;
      this.collapseValues = collapseValuesProducer.getSorted(null);
      if(collapseValues instanceof MultiDocValues.MultiSortedDocValues) {
        this.multiSortedDocValues = (MultiDocValues.MultiSortedDocValues)collapseValues;
        this.ordinalMap = multiSortedDocValues.mapping;
      }

      int valueCount = collapseValues.getValueCount();
      this.nullPolicy = nullPolicy;
      this.needsScores4Collapsing = needsScores4Collapsing;
      this.needsScores = needsScores;
      if (null != sortSpec) {
        this.collapseStrategy = new OrdSortSpecStrategy(maxDoc, nullPolicy, valueCount, groupHeadSelector, this.needsScores4Collapsing, this.needsScores, boostDocs, sortSpec, searcher, collapseValues);
      } else if (funcQuery != null) {
        this.collapseStrategy =  new OrdValueSourceStrategy(maxDoc, nullPolicy, valueCount, groupHeadSelector, this.needsScores4Collapsing, this.needsScores, boostDocs, funcQuery, searcher, collapseValues);
      } else {
        NumberType numType = fieldType.getNumberType();
        if (null == numType) {
          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "min/max must be either Int/Long/Float based field types");
        }
        switch (numType) {
          case INTEGER: {
            this.collapseStrategy = new OrdIntStrategy(maxDoc, nullPolicy, valueCount, groupHeadSelector, this.needsScores, boostDocs, collapseValues);
            break;
          }
          case FLOAT: {
            this.collapseStrategy = new OrdFloatStrategy(maxDoc, nullPolicy, valueCount, groupHeadSelector, this.needsScores, boostDocs, collapseValues);
            break;
          }
          case LONG: {
            this.collapseStrategy =  new OrdLongStrategy(maxDoc, nullPolicy, valueCount, groupHeadSelector, this.needsScores, boostDocs, collapseValues);
            break;
          }
          default: {
            throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "min/max must be either Int/Long/Float field types");
          }
        }
      }
    }

    @Override public ScoreMode scoreMode() { return needsScores ? ScoreMode.COMPLETE : super.scoreMode(); }

    public void setScorer(Scorable scorer) throws IOException {
      this.collapseStrategy.setScorer(scorer);
    }

    public void doSetNextReader(LeafReaderContext context) throws IOException {
      this.contexts[context.ord] = context;
      this.docBase = context.docBase;
      this.collapseStrategy.setNextReader(context);
      if(ordinalMap != null) {
        this.segmentValues = this.multiSortedDocValues.values[context.ord];
        this.segmentOrdinalMap = ordinalMap.getGlobalOrds(context.ord);
      } else {
        this.segmentValues = collapseValues;
      }
    }

    public void collect(int contextDoc) throws IOException {
      int globalDoc = contextDoc+this.docBase;
      int ord = -1;
      if(this.ordinalMap != null) {
        if (segmentValues.advanceExact(contextDoc)) {
          ord = (int)segmentOrdinalMap.get(segmentValues.ordValue());
        }
      } else {
        if (segmentValues.advanceExact(globalDoc)) {
          ord = segmentValues.ordValue();
        }
      }
      collapseStrategy.collapse(ord, contextDoc, globalDoc);
    }

    public void finish() throws IOException {
      if(contexts.length == 0) {
        return;
      }

      int currentContext = 0;
      int currentDocBase = 0;

      this.collapseValues = collapseValuesProducer.getSorted(null);
      if(collapseValues instanceof MultiDocValues.MultiSortedDocValues) {
        this.multiSortedDocValues = (MultiDocValues.MultiSortedDocValues)collapseValues;
        this.ordinalMap = multiSortedDocValues.mapping;
      }
      if(ordinalMap != null) {
        this.segmentValues = this.multiSortedDocValues.values[currentContext];
        this.segmentOrdinalMap = this.ordinalMap.getGlobalOrds(currentContext);
      } else {
        this.segmentValues = collapseValues;
      }

      int nextDocBase = currentContext+1 < contexts.length ? contexts[currentContext+1].docBase : maxDoc;
      leafDelegate = delegate.getLeafCollector(contexts[currentContext]);
      ScoreAndDoc dummy = new ScoreAndDoc();
      leafDelegate.setScorer(dummy);
      DocIdSetIterator it = new BitSetIterator(collapseStrategy.getCollapsedSet(), 0); // cost is not useful here
      int globalDoc = -1;
      int nullScoreIndex = 0;
      IntFloatDynamicMap scores = collapseStrategy.getScores();
      FloatArrayList nullScores = collapseStrategy.getNullScores();
      float nullScore = collapseStrategy.getNullScore();

      MergeBoost mergeBoost = collapseStrategy.getMergeBoost();
      while((globalDoc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {


        while(globalDoc >= nextDocBase) {
          currentContext++;
          currentDocBase = contexts[currentContext].docBase;
          nextDocBase = currentContext+1 < contexts.length ? contexts[currentContext+1].docBase : maxDoc;
          leafDelegate = delegate.getLeafCollector(contexts[currentContext]);
          leafDelegate.setScorer(dummy);
          if(ordinalMap != null) {
            this.segmentValues = this.multiSortedDocValues.values[currentContext];
            this.segmentOrdinalMap = this.ordinalMap.getGlobalOrds(currentContext);
          }
        }

        int contextDoc = globalDoc-currentDocBase;

        if(this.needsScores){
          int ord = -1;
          if(this.ordinalMap != null) {
            //Handle ordinalMapping case
            if (segmentValues.advanceExact(contextDoc)) {
              ord = (int) segmentOrdinalMap.get(segmentValues.ordValue());
            }
          } else {
            //Handle top Level FieldCache or Single Segment Case
            if (segmentValues.advanceExact(globalDoc)) {
              ord = segmentValues.ordValue();
            }
          }

          if(ord > -1) {
            dummy.score = scores.get(ord);
          } else if (mergeBoost != null && mergeBoost.boost(globalDoc)) {
            //It's an elevated doc so no score is needed
            dummy.score = 0F;
          } else if (nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
            dummy.score = nullScore;
          } else if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
            dummy.score = nullScores.get(nullScoreIndex++);
          }
        }

        dummy.docId = contextDoc;
        leafDelegate.collect(contextDoc);
      }

      if(delegate instanceof DelegatingCollector) {
        ((DelegatingCollector) delegate).finish();
      }
    }
  }


  /**
   *  Collapses on an integer field.
   */
  private static class IntFieldValueCollector extends DelegatingCollector {
    private LeafReaderContext[] contexts;
    private NumericDocValues collapseValues;
    private int maxDoc;
    private int nullValue;
    private int nullPolicy;

    private IntFieldValueStrategy collapseStrategy;
    private boolean needsScores4Collapsing;
    private boolean needsScores;
    private String collapseField;

    public IntFieldValueCollector(int maxDoc,
                                  int size,
                                  int segments,
                                  int nullValue,
                                  int nullPolicy,
                                  String collapseField,
                                  GroupHeadSelector groupHeadSelector,
                                  SortSpec sortSpec,
                                  boolean needsScores4Collapsing,
                                  boolean needsScores,
                                  FieldType fieldType,
                                  IntIntHashMap boostDocsMap,
                                  FunctionQuery funcQuery,
                                  IndexSearcher searcher) throws IOException{

      assert ! GroupHeadSelectorType.SCORE.equals(groupHeadSelector.type);

      this.maxDoc = maxDoc;
      this.contexts = new LeafReaderContext[segments];
      List<LeafReaderContext> con = searcher.getTopReaderContext().leaves();
      for(int i=0; i<con.size(); i++) {
        contexts[i] = con.get(i);
      }
      this.collapseField = collapseField;
      this.nullValue = nullValue;
      this.nullPolicy = nullPolicy;
      this.needsScores4Collapsing = needsScores4Collapsing;
      this.needsScores = needsScores;
      if (null != sortSpec) {
        this.collapseStrategy = new IntSortSpecStrategy(maxDoc, size, collapseField, nullValue, nullPolicy, groupHeadSelector, this.needsScores4Collapsing, this.needsScores, boostDocsMap, sortSpec, searcher);
      } else if (funcQuery != null) {
        this.collapseStrategy =  new IntValueSourceStrategy(maxDoc, size, collapseField, nullValue, nullPolicy, groupHeadSelector, this.needsScores4Collapsing, this.needsScores, boostDocsMap, funcQuery, searcher);
      } else {
        NumberType numType = fieldType.getNumberType();
        assert null != numType; // shouldn't make it here for non-numeric types
        switch (numType) {
          case INTEGER: {
            this.collapseStrategy = new IntIntStrategy(maxDoc, size, collapseField, nullValue, nullPolicy, groupHeadSelector, this.needsScores, boostDocsMap);
            break;
          }
          case FLOAT: {
            this.collapseStrategy = new IntFloatStrategy(maxDoc, size, collapseField, nullValue, nullPolicy, groupHeadSelector, this.needsScores, boostDocsMap);
            break;
          }
          default: {
            throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
                "min/max must be Int or Float field types when collapsing on numeric fields");
          }
        }
      }
    }

    @Override public ScoreMode scoreMode() { return needsScores ? ScoreMode.COMPLETE : super.scoreMode(); }

    @Override
    public void setScorer(Scorable scorer) throws IOException {
      this.collapseStrategy.setScorer(scorer);
    }

    public void doSetNextReader(LeafReaderContext context) throws IOException {
      this.contexts[context.ord] = context;
      this.docBase = context.docBase;
      this.collapseStrategy.setNextReader(context);
      this.collapseValues = DocValues.getNumeric(context.reader(), this.collapseField);
    }

    public void collect(int contextDoc) throws IOException {
      int collapseKey;
      if (collapseValues.advanceExact(contextDoc)) {
        collapseKey = (int) collapseValues.longValue();
      } else {
        collapseKey = 0;
      }

      int globalDoc = contextDoc+this.docBase;
      collapseStrategy.collapse(collapseKey, contextDoc, globalDoc);
    }

    public void finish() throws IOException {
      if(contexts.length == 0) {
        return;
      }

      int currentContext = 0;
      int currentDocBase = 0;
      this.collapseValues = DocValues.getNumeric(contexts[currentContext].reader(), this.collapseField);
      int nextDocBase = currentContext+1 < contexts.length ? contexts[currentContext+1].docBase : maxDoc;
      leafDelegate = delegate.getLeafCollector(contexts[currentContext]);
      ScoreAndDoc dummy = new ScoreAndDoc();
      leafDelegate.setScorer(dummy);
      DocIdSetIterator it = new BitSetIterator(collapseStrategy.getCollapsedSet(), 0); // cost is not useful here
      int globalDoc = -1;
      int nullScoreIndex = 0;
      IntIntHashMap cmap = collapseStrategy.getCollapseMap();
      IntFloatDynamicMap scores = collapseStrategy.getScores();
      FloatArrayList nullScores = collapseStrategy.getNullScores();
      MergeBoost mergeBoost = collapseStrategy.getMergeBoost();
      float nullScore = collapseStrategy.getNullScore();

      while((globalDoc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {

        while(globalDoc >= nextDocBase) {
          currentContext++;
          currentDocBase = contexts[currentContext].docBase;
          nextDocBase = currentContext+1 < contexts.length ? contexts[currentContext+1].docBase : maxDoc;
          leafDelegate = delegate.getLeafCollector(contexts[currentContext]);
          leafDelegate.setScorer(dummy);
          this.collapseValues = DocValues.getNumeric(contexts[currentContext].reader(), this.collapseField);
        }

        int contextDoc = globalDoc-currentDocBase;

        if(this.needsScores){
          int collapseValue;
          if (collapseValues.advanceExact(contextDoc)) {
            collapseValue = (int) collapseValues.longValue();
          } else {
            collapseValue = 0;
          }
          
          if(collapseValue != nullValue) {
            int pointer = cmap.get(collapseValue);
            dummy.score = scores.get(pointer);
          } else if (mergeBoost != null && mergeBoost.boost(globalDoc)) {
            //Its an elevated doc so no score is needed
            dummy.score = 0F;
          } else if (nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
            dummy.score = nullScore;
          } else if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
            dummy.score = nullScores.get(nullScoreIndex++);
          }
        }

        dummy.docId = contextDoc;
        leafDelegate.collect(contextDoc);
      }

      if(delegate instanceof DelegatingCollector) {
        ((DelegatingCollector) delegate).finish();
      }
    }
  }

  private static class CollectorFactory {
    /** @see #isNumericCollapsible */
    private final static EnumSet<NumberType> NUMERIC_COLLAPSIBLE_TYPES = EnumSet.of(NumberType.INTEGER,
                                                                                    NumberType.FLOAT);
    private boolean isNumericCollapsible(FieldType collapseFieldType) {
      return NUMERIC_COLLAPSIBLE_TYPES.contains(collapseFieldType.getNumberType());
    }

    public DelegatingCollector getCollector(String collapseField,
                                            GroupHeadSelector groupHeadSelector,
                                            SortSpec sortSpec,
                                            int nullPolicy,
                                            String hint,
                                            boolean needsScores4Collapsing,
                                            boolean needsScores,
                                            int size,
                                            IntIntHashMap boostDocs,
                                            SolrIndexSearcher searcher) throws IOException {

      DocValuesProducer docValuesProducer = null;
      FunctionQuery funcQuery = null;

      FieldType collapseFieldType = searcher.getSchema().getField(collapseField).getType();
      String defaultValue = searcher.getSchema().getField(collapseField).getDefaultValue();

      if(collapseFieldType instanceof StrField) {
        if(HINT_TOP_FC.equals(hint)) {
          @SuppressWarnings("resource")
          final LeafReader uninvertingReader = getTopFieldCacheReader(searcher, collapseField);

          docValuesProducer = new EmptyDocValuesProducer() {
              @Override
              public SortedDocValues getSorted(FieldInfo ignored) throws IOException {
                return uninvertingReader.getSortedDocValues(collapseField);
              }
            };
        } else {
          docValuesProducer = new EmptyDocValuesProducer() {
              @Override
              public SortedDocValues getSorted(FieldInfo ignored) throws IOException {
                return DocValues.getSorted(searcher.getSlowAtomicReader(), collapseField);
              }
            };
        }
      } else {
        if(HINT_TOP_FC.equals(hint)) {
          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
              "top_fc hint is only supported when collapsing on String Fields");
        }
      }

      FieldType minMaxFieldType = null;
      if (GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type)) {
        final String text = groupHeadSelector.selectorText;
        if (text.indexOf("(") == -1) {
          minMaxFieldType = searcher.getSchema().getField(text).getType();
        } else {
          SolrParams params = new ModifiableSolrParams();
          try (SolrQueryRequest request = new LocalSolrQueryRequest(searcher.getCore(), params)) {
            FunctionQParser functionQParser = new FunctionQParser(text, null, null,request);
            funcQuery = (FunctionQuery)functionQParser.parse();
          } catch (SyntaxError e) {
            throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
          }
        }
      }

      int maxDoc = searcher.maxDoc();
      int leafCount = searcher.getTopReaderContext().leaves().size();

      if (GroupHeadSelectorType.SCORE.equals(groupHeadSelector.type)) {

        if (collapseFieldType instanceof StrField) {

          return new OrdScoreCollector(maxDoc, leafCount, docValuesProducer, nullPolicy, boostDocs, searcher);

        } else if (isNumericCollapsible(collapseFieldType)) {

          int nullValue = 0;

          // must be non-null at this point
          if (collapseFieldType.getNumberType().equals(NumberType.FLOAT)) {
            if (defaultValue != null) {
              nullValue = Float.floatToIntBits(Float.parseFloat(defaultValue));
            } else {
              nullValue = Float.floatToIntBits(0.0f);
            }
          } else {
            if (defaultValue != null) {
              nullValue = Integer.parseInt(defaultValue);
            }
          }

          return new IntScoreCollector(maxDoc, leafCount, nullValue, nullPolicy, size, collapseField, boostDocs, searcher);

        } else {
          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
              "Collapsing field should be of either String, Int or Float type");
        }

      } else { // min, max, sort, etc.. something other then just "score"

        if (collapseFieldType instanceof StrField) {

          return new OrdFieldValueCollector(maxDoc,
                                            leafCount,
                                            docValuesProducer,
                                            nullPolicy,
                                            groupHeadSelector,
                                            sortSpec,
                                            needsScores4Collapsing,
                                            needsScores,
                                            minMaxFieldType,
                                            boostDocs,
                                            funcQuery,
                                            searcher);

        } else if (isNumericCollapsible(collapseFieldType)) {

          int nullValue = 0;

          // must be non-null at this point
          if (collapseFieldType.getNumberType().equals(NumberType.FLOAT)) {
            if (defaultValue != null) {
              nullValue = Float.floatToIntBits(Float.parseFloat(defaultValue));
            } else {
              nullValue = Float.floatToIntBits(0.0f);
            }
          } else {
            if (defaultValue != null) {
              nullValue = Integer.parseInt(defaultValue);
            }
          }

          return new IntFieldValueCollector(maxDoc,
                                            size,
                                            leafCount,
                                            nullValue,
                                            nullPolicy,
                                            collapseField,
                                            groupHeadSelector,
                                            sortSpec,
                                            needsScores4Collapsing,
                                            needsScores,
                                            minMaxFieldType,
                                            boostDocs,
                                            funcQuery,
                                            searcher);
        } else {
          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
              "Collapsing field should be of either String, Int or Float type");
        }

      }
    }
  }

  public static final class CollapseScore {
    /**
     * Inspects the GroupHeadSelector to determine if this CollapseScore is needed.
     * If it is, then "this" will be added to the readerContext
     * using the "CSCORE" key, and true will be returned.  If not returns false.
     */
    @SuppressWarnings({"unchecked"})
    public boolean setupIfNeeded(final GroupHeadSelector groupHeadSelector,
                                 @SuppressWarnings({"rawtypes"})final Map readerContext) {
      // HACK, but not really any better options until/unless we can recursively
      // ask value sources if they depend on score
      if (wantsCScore(groupHeadSelector.selectorText)) {
        readerContext.put("CSCORE", this);
        return true;
      }
      return false;
    }

    /**
     * Huge HACK, but not really any better options until/unless we can recursively
     * ask value sources if they depend on score
     */
    public static boolean wantsCScore(final String text) {
      return (0 <= text.indexOf("cscore()"));
    }

    private CollapseScore() {
      // No-Op
    }

    public float score;
  }


  /*
  * Collapse Strategies
  */

  /**
   * The abstract base Strategy for collapse strategies that collapse on an ordinal
   * using min/max field value to select the group head.
   *
   */
  private static abstract class OrdFieldValueStrategy {
    protected int nullPolicy;
    protected IntIntDynamicMap ords;
    protected Scorable scorer;
    protected FloatArrayList nullScores;
    protected float nullScore;
    protected IntFloatDynamicMap scores;
    protected FixedBitSet collapsedSet;
    protected int nullDoc = -1;
    protected boolean needsScores;
    protected boolean boosts;
    protected IntArrayList boostOrds;
    protected IntArrayList boostDocs;
    protected MergeBoost mergeBoost;
    protected boolean boosted;

    public abstract void collapse(int ord, int contextDoc, int globalDoc) throws IOException;
    public abstract void setNextReader(LeafReaderContext context) throws IOException;

    public OrdFieldValueStrategy(int maxDoc,
                                 int valueCount,
                                 int nullPolicy,
                                 boolean needsScores,
                                 IntIntHashMap boostDocsMap,
                                 SortedDocValues values) {
      this.ords = new IntIntDynamicMap(valueCount, -1);
      this.nullPolicy = nullPolicy;
      this.needsScores = needsScores;
      this.collapsedSet = new FixedBitSet(maxDoc);
      if(boostDocsMap != null) {
        this.boosts = true;
        this.boostOrds = new IntArrayList();
        this.boostDocs = new IntArrayList();
        int[] bd = new int[boostDocsMap.size()];
        Iterator<IntIntCursor> it =  boostDocsMap.iterator();
        int index = -1;
        while(it.hasNext()) {
          IntIntCursor cursor = it.next();
          bd[++index] = cursor.key;
        }

        Arrays.sort(bd);
        this.mergeBoost = new MergeBoost(bd);
        this.boosted = true;
      }

      if (this.needsScores) {
        this.scores = new IntFloatDynamicMap(valueCount, 0.0f);
        if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
          nullScores = new FloatArrayList();
        }
      }
    }

    public MergeBoost getMergeBoost() {
      return this.mergeBoost;
    }

    public FixedBitSet getCollapsedSet() {
      if(nullDoc > -1) {
        this.collapsedSet.set(nullDoc);
      }

      if(this.boostOrds != null) {
        int s = boostOrds.size();
        for(int i=0; i<s; i++) {
          int ord = boostOrds.get(i);
          if(ord > -1) {
            ords.remove(ord);
          }
          collapsedSet.set(boostDocs.get(i));
        }

        mergeBoost.reset();
      }

      ords.forEachValue(doc -> collapsedSet.set(doc));

      return collapsedSet;
    }

    public void setScorer(Scorable scorer) throws IOException {
      this.scorer = scorer;
    }

    public FloatArrayList getNullScores() {
      return nullScores;
    }

    public float getNullScore() {
      return this.nullScore;
    }

    public IntFloatDynamicMap getScores() {
      return scores;
    }
  }

  /*
   * Strategy for collapsing on ordinal using min/max of an int field to select the group head.
   */
  private static class OrdIntStrategy extends OrdFieldValueStrategy {

    private final String field;
    private NumericDocValues minMaxValues;
    private IntCompare comp;
    private int nullVal;
    private IntIntDynamicMap ordVals;

    public OrdIntStrategy(int maxDoc,
                          int nullPolicy,
                          int valueCount,
                          GroupHeadSelector groupHeadSelector,
                          boolean needsScores,
                          IntIntHashMap boostDocs,
                          SortedDocValues values) throws IOException {
      super(maxDoc, valueCount, nullPolicy, needsScores, boostDocs, values);
      this.field = groupHeadSelector.selectorText;

      assert GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type);

      if (GroupHeadSelectorType.MAX.equals(groupHeadSelector.type)) {
        comp = new MaxIntComp();
        this.ordVals = new IntIntDynamicMap(valueCount, Integer.MIN_VALUE);
      } else {
        comp = new MinIntComp();
        this.ordVals = new IntIntDynamicMap(valueCount, Integer.MAX_VALUE);
        this.nullVal = Integer.MAX_VALUE;
      }
    }

    public void setNextReader(LeafReaderContext context) throws IOException {
      this.minMaxValues = DocValues.getNumeric(context.reader(), this.field);
    }

    public void collapse(int ord, int contextDoc, int globalDoc) throws IOException {

      if(this.boosted && mergeBoost.boost(globalDoc)) {
        this.boostDocs.add(globalDoc);
        this.boostOrds.add(ord);
        return;
      }

      int currentVal;
      if (minMaxValues.advanceExact(contextDoc)) {
        currentVal = (int) minMaxValues.longValue();
      } else {
        currentVal = 0;
      }

      if(ord > -1) {
        if(comp.test(currentVal, ordVals.get(ord))) {
          ords.put(ord, globalDoc);
          ordVals.put(ord, currentVal);
          if(needsScores) {
            scores.put(ord, scorer.score());
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if(comp.test(currentVal, nullVal)) {
          nullVal = currentVal;
          nullDoc = globalDoc;
          if(needsScores) {
            nullScore = scorer.score();
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if(needsScores) {
          nullScores.add(scorer.score());
        }
      }
    }
  }

  /**
   * Strategy for collapsing on ordinal and using the min/max value of a float
   * field to select the group head
   */
  private static class OrdFloatStrategy extends OrdFieldValueStrategy {

    private final String field;
    private NumericDocValues minMaxValues;
    private FloatCompare comp;
    private float nullVal;
    private IntFloatDynamicMap ordVals;

    public OrdFloatStrategy(int maxDoc,
                            int nullPolicy,
                            int valueCount,
                            GroupHeadSelector groupHeadSelector,
                            boolean needsScores,
                            IntIntHashMap boostDocs,
                            SortedDocValues values) throws IOException {
      super(maxDoc, valueCount, nullPolicy, needsScores, boostDocs, values);
      this.field = groupHeadSelector.selectorText;

      assert GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type);

      if (GroupHeadSelectorType.MAX.equals(groupHeadSelector.type)) {
        comp = new MaxFloatComp();
        this.ordVals = new IntFloatDynamicMap(valueCount, -Float.MAX_VALUE);
        this.nullVal = -Float.MAX_VALUE;
      } else {
        comp = new MinFloatComp();
        this.ordVals = new IntFloatDynamicMap(valueCount, Float.MAX_VALUE);
        this.nullVal = Float.MAX_VALUE;
      }
    }

    public void setNextReader(LeafReaderContext context) throws IOException {
      this.minMaxValues = DocValues.getNumeric(context.reader(), this.field);
    }

    public void collapse(int ord, int contextDoc, int globalDoc) throws IOException {

      if(this.boosted && mergeBoost.boost(globalDoc)) {
        this.boostDocs.add(globalDoc);
        this.boostOrds.add(ord);
        return;
      }

      int currentMinMax;
      if (minMaxValues.advanceExact(contextDoc)) {
        currentMinMax = (int) minMaxValues.longValue();
      } else {
        currentMinMax = 0;
      }

      float currentVal = Float.intBitsToFloat(currentMinMax);

      if(ord > -1) {
        if(comp.test(currentVal, ordVals.get(ord))) {
          ords.put(ord, globalDoc);
          ordVals.put(ord, currentVal);
          if(needsScores) {
            scores.put(ord, scorer.score());
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if(comp.test(currentVal, nullVal)) {
          nullVal = currentVal;
          nullDoc = globalDoc;
          if(needsScores) {
            nullScore = scorer.score();
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if(needsScores) {
          nullScores.add(scorer.score());
        }
      }
    }
  }

  /*
  * Strategy for collapsing on ordinal and using the min/max value of a long
  * field to select the group head
  */

  private static class OrdLongStrategy extends OrdFieldValueStrategy {

    private final String field;
    private NumericDocValues minMaxVals;
    private LongCompare comp;
    private long nullVal;
    private IntLongDynamicMap ordVals;

    public OrdLongStrategy(int maxDoc,
                           int nullPolicy,
                           int valueCount,
                           GroupHeadSelector groupHeadSelector,
                           boolean needsScores,
                           IntIntHashMap boostDocs, SortedDocValues values) throws IOException {
      super(maxDoc, valueCount, nullPolicy, needsScores, boostDocs, values);
      this.field = groupHeadSelector.selectorText;

      assert GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type);

      if (GroupHeadSelectorType.MAX.equals(groupHeadSelector.type)) {
        comp = new MaxLongComp();
        this.ordVals = new IntLongDynamicMap(valueCount, Long.MIN_VALUE);
      } else {
        this.nullVal = Long.MAX_VALUE;
        comp = new MinLongComp();
        this.ordVals = new IntLongDynamicMap(valueCount, Long.MAX_VALUE);
      }
    }

    public void setNextReader(LeafReaderContext context) throws IOException {
      this.minMaxVals = DocValues.getNumeric(context.reader(), this.field);
    }

    public void collapse(int ord, int contextDoc, int globalDoc) throws IOException {

      if(boosted && mergeBoost.boost(globalDoc)) {
        this.boostOrds.add(ord);
        this.boostDocs.add(globalDoc);
        return;
      }

      long currentVal;
      if (minMaxVals.advanceExact(contextDoc)) {
        currentVal = minMaxVals.longValue();
      } else {
        currentVal = 0;
      }

      if(ord > -1) {
        if(comp.test(currentVal, ordVals.get(ord))) {
          ords.put(ord, globalDoc);
          ordVals.put(ord, currentVal);
          if(needsScores) {
            scores.put(ord, scorer.score());
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if(comp.test(currentVal, nullVal)) {
          nullVal = currentVal;
          nullDoc = globalDoc;
          if(needsScores) {
            nullScore = scorer.score();
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if(needsScores) {
          nullScores.add(scorer.score());
        }
      }
    }
  }

  /*
   * Strategy for collapsing on ordinal and using the min/max value of a value source function
   * to select the group head
   */
  private static class OrdValueSourceStrategy extends OrdFieldValueStrategy {

    private FloatCompare comp;
    private float nullVal;
    private ValueSource valueSource;
    private FunctionValues functionValues;
    private IntFloatDynamicMap ordVals;
    @SuppressWarnings({"rawtypes"})
    private Map rcontext;
    private final CollapseScore collapseScore = new CollapseScore();
    private boolean needsScores4Collapsing;

    public OrdValueSourceStrategy(int maxDoc,
                                  int nullPolicy,
                                  int valueCount,
                                  GroupHeadSelector groupHeadSelector,
                                  boolean needsScores4Collapsing,
                                  boolean needsScores,
                                  IntIntHashMap boostDocs,
                                  FunctionQuery funcQuery,
                                  IndexSearcher searcher,
                                  SortedDocValues values) throws IOException {
      super(maxDoc, valueCount, nullPolicy, needsScores, boostDocs, values);
      this.needsScores4Collapsing = needsScores4Collapsing;
      this.valueSource = funcQuery.getValueSource();
      this.rcontext = ValueSource.newContext(searcher);

      assert GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type);

      if (GroupHeadSelectorType.MAX.equals(groupHeadSelector.type)) {
        comp = new MaxFloatComp();
        this.ordVals = new IntFloatDynamicMap(valueCount, -Float.MAX_VALUE);
      } else {
        this.nullVal = Float.MAX_VALUE;
        comp = new MinFloatComp();
        this.ordVals = new IntFloatDynamicMap(valueCount, Float.MAX_VALUE);
      }

      collapseScore.setupIfNeeded(groupHeadSelector, rcontext);
    }

    @SuppressWarnings({"unchecked"})
    public void setNextReader(LeafReaderContext context) throws IOException {
      functionValues = this.valueSource.getValues(rcontext, context);
    }

    public void collapse(int ord, int contextDoc, int globalDoc) throws IOException {
      float score = 0;

      if(boosted && mergeBoost.boost(globalDoc)) {
        this.boostOrds.add(ord);
        this.boostDocs.add(globalDoc);
      }

      if (needsScores4Collapsing) {
        score = scorer.score();
        this.collapseScore.score = score;
      }

      float currentVal = functionValues.floatVal(contextDoc);

      if(ord > -1) {
        if(comp.test(currentVal, ordVals.get(ord))) {
          ords.put(ord, globalDoc);
          ordVals.put(ord, currentVal);
          if(needsScores) {
            if (!needsScores4Collapsing) {
              score = scorer.score();
            }
            scores.put(ord, score);
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if(comp.test(currentVal, nullVal)) {
          nullVal = currentVal;
          nullDoc = globalDoc;
          if(needsScores) {
            if (!needsScores4Collapsing) {
              score = scorer.score();
            }
            nullScore = score;
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if(needsScores) {
          if (!needsScores4Collapsing) {
            score = scorer.score();
          }
          nullScores.add(score);
        }
      }
    }
  }

  /*
   * Strategy for collapsing on ordinal and using the first document according to a complex sort
   * as the group head
   */
  private static class OrdSortSpecStrategy extends OrdFieldValueStrategy {

    private final SortFieldsCompare compareState;
    private final Sort sort;

    private float score;
    private boolean needsScores4Collapsing;

    public OrdSortSpecStrategy(int maxDoc,
                               int nullPolicy,
                               int valueCount,
                               GroupHeadSelector groupHeadSelector,
                               boolean needsScores4Collapsing,
                               boolean needsScores,
                               IntIntHashMap boostDocs,
                               SortSpec sortSpec,
                               IndexSearcher searcher,
                               SortedDocValues values) throws IOException {
      super(maxDoc, valueCount, nullPolicy, needsScores, boostDocs, values);
      this.needsScores4Collapsing = needsScores4Collapsing;

      assert GroupHeadSelectorType.SORT.equals(groupHeadSelector.type);

      this.sort = rewriteSort(sortSpec, searcher);

      this.compareState = new SortFieldsCompare(sort.getSort(), valueCount);
    }

    @Override
    public void setNextReader(LeafReaderContext context) throws IOException {
      compareState.setNextReader(context);
    }

    @Override
    public void setScorer(Scorable s) throws IOException {
      super.setScorer(s);
      this.compareState.setScorer(s);
    }

    @Override
    public void collapse(int ord, int contextDoc, int globalDoc) throws IOException {

      if(boosted && mergeBoost.boost(globalDoc)) {
        this.boostOrds.add(ord);
        this.boostDocs.add(globalDoc);
      }

      if (needsScores4Collapsing) {
        this.score = scorer.score();
      }

      if (ord > -1) { // real collapseKey
        if (-1 == ords.get(ord)) {
          // we've never seen this ord (aka: collapseKey) before, treat it as group head for now
          compareState.setGroupValues(ord, contextDoc);
          ords.put(ord, globalDoc);
          if (needsScores) {
            if (!needsScores4Collapsing) {
              this.score = scorer.score();
            }
            scores.put(ord, score);
          }
        } else {
          // test this ord to see if it's a new group leader
          if (compareState.testAndSetGroupValues(ord, contextDoc)) {//TODO X
            ords.put(ord, globalDoc);
            if (needsScores) {
              if (!needsScores4Collapsing) {
                this.score = scorer.score();
              }
              scores.put(ord, score);
            }
          }
        }
      } else if (this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if (-1 == nullDoc) {
          // we've never seen a doc with null collapse key yet, treat it as the null group head for now
          compareState.setNullGroupValues(contextDoc);
          nullDoc = globalDoc;
          if (needsScores) {
            if (!needsScores4Collapsing) {
              this.score = scorer.score();
            }
            nullScore = score;
          }
        } else {
          // test this doc to see if it's the new null leader
          if (compareState.testAndSetNullGroupValues(contextDoc)) {
            nullDoc = globalDoc;
            if (needsScores) {
              if (!needsScores4Collapsing) {
                this.score = scorer.score();
              }
              nullScore = score;
            }
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if (needsScores) {
          if (!needsScores4Collapsing) {
            this.score = scorer.score();
          }
          nullScores.add(score);
        }
      }
    }
  }

  /*
  * Base strategy for collapsing on a 32 bit numeric field and selecting a group head
  * based on min/max value of a 32 bit numeric field.
  */

  private static abstract class IntFieldValueStrategy {
    protected int nullPolicy;
    protected IntIntHashMap cmap;
    protected Scorable scorer;
    protected FloatArrayList nullScores;
    protected float nullScore;
    protected IntFloatDynamicMap scores;
    protected FixedBitSet collapsedSet;
    protected int nullDoc = -1;
    protected boolean needsScores;
    protected String collapseField;
    protected IntIntDynamicMap docs;
    protected int nullValue;
    protected IntArrayList boostDocs;
    protected IntArrayList boostKeys;
    protected boolean boosts;
    protected MergeBoost mergeBoost;

    public abstract void collapse(int collapseKey, int contextDoc, int globalDoc) throws IOException;
    public abstract void setNextReader(LeafReaderContext context) throws IOException;

    public IntFieldValueStrategy(int maxDoc,
                                 int size,
                                 String collapseField,
                                 int nullValue,
                                 int nullPolicy,
                                 boolean needsScores,
                                 IntIntHashMap boostDocsMap) {
      this.collapseField = collapseField;
      this.nullValue = nullValue;
      this.nullPolicy = nullPolicy;
      this.needsScores = needsScores;
      this.collapsedSet = new FixedBitSet(maxDoc);
      this.cmap = new IntIntHashMap(size);
      this.docs = new IntIntDynamicMap(size, 0);
      if(boostDocsMap != null) {
        this.boosts = true;
        this.boostDocs = new IntArrayList();
        this.boostKeys = new IntArrayList();
        int[] bd = new int[boostDocsMap.size()];
        Iterator<IntIntCursor> it =  boostDocsMap.iterator();
        int index = -1;
        while(it.hasNext()) {
          IntIntCursor cursor = it.next();
          bd[++index] = cursor.key;
        }

        Arrays.sort(bd);
        this.mergeBoost = new MergeBoost(bd);
      }

      if(needsScores) {
        this.scores = new IntFloatDynamicMap(size, 0.0f);
        if(nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
          nullScores = new FloatArrayList();
        }
      }
    }

    public FixedBitSet getCollapsedSet() {

      if(nullDoc > -1) {
        this.collapsedSet.set(nullDoc);
      }

      //Handle the boosted docs.
      if(this.boostKeys != null) {
        int s = boostKeys.size();
        for(int i=0; i<s; i++) {
          int key = this.boostKeys.get(i);
          if(key != nullValue) {
            cmap.remove(key);
          }
          //Add the boosted docs to the collapsedSet
          this.collapsedSet.set(boostDocs.get(i));
        }

        mergeBoost.reset();
      }

      Iterator<IntIntCursor> it1 = cmap.iterator();
      while(it1.hasNext()) {
        IntIntCursor cursor = it1.next();
        int pointer = cursor.value;
        collapsedSet.set(docs.get(pointer));
      }

      return collapsedSet;
    }

    public void setScorer(Scorable scorer) throws IOException {
      this.scorer = scorer;
    }

    public FloatArrayList getNullScores() {
      return nullScores;
    }

    public IntIntHashMap getCollapseMap() {
      return cmap;
    }

    public float getNullScore() {
      return this.nullScore;
    }

    public IntFloatDynamicMap getScores() {
      return scores;
    }

    public IntIntDynamicMap getDocs() { return docs;}

    public MergeBoost getMergeBoost()  {
      return this.mergeBoost;
    }
  }

  /*
   *  Strategy for collapsing on a 32 bit numeric field and selecting the group head based
   *  on the min/max value of a 32 bit field numeric field.
   */
  private static class IntIntStrategy extends IntFieldValueStrategy {

    private final String field;
    private NumericDocValues minMaxVals;
    private IntIntDynamicMap testValues;
    private IntCompare comp;
    private int nullCompVal;

    private int index=-1;

    public IntIntStrategy(int maxDoc,
                          int size,
                          String collapseField,
                          int nullValue,
                          int nullPolicy,
                          GroupHeadSelector groupHeadSelector,
                          boolean needsScores,
                          IntIntHashMap boostDocs) throws IOException {

      super(maxDoc, size, collapseField, nullValue, nullPolicy, needsScores, boostDocs);
      this.field = groupHeadSelector.selectorText;
      this.testValues = new IntIntDynamicMap(size, 0);

      assert GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type);

      if (GroupHeadSelectorType.MAX.equals(groupHeadSelector.type)) {
        comp = new MaxIntComp();
        this.nullCompVal = Integer.MIN_VALUE;
      } else {
        comp = new MinIntComp();
        this.nullCompVal = Integer.MAX_VALUE;
      }
    }

    public void setNextReader(LeafReaderContext context) throws IOException {
      this.minMaxVals = DocValues.getNumeric(context.reader(), this.field);
    }

    public void collapse(int collapseKey, int contextDoc, int globalDoc) throws IOException {

      // Check to see if we have documents boosted by the QueryElevationComponent
      if(boosts && mergeBoost.boost(globalDoc)) {
        boostDocs.add(globalDoc);
        boostKeys.add(collapseKey);
        return;
      }

      int currentVal;
      if (minMaxVals.advanceExact(contextDoc)) {
        currentVal = (int) minMaxVals.longValue();
      } else {
        currentVal = 0;
      }

      if(collapseKey != nullValue) {
        final int idx;
        if((idx = cmap.indexOf(collapseKey)) >= 0) {
          int pointer = cmap.indexGet(idx);
          if(comp.test(currentVal, testValues.get(pointer))) {
            testValues.put(pointer, currentVal);
            docs.put(pointer, globalDoc);
            if(needsScores) {
              scores.put(pointer, scorer.score());
            }
          }
        } else {
          ++index;
          cmap.put(collapseKey, index);
          testValues.put(index, currentVal);
          docs.put(index, globalDoc);
          if(needsScores) {
            scores.put(index, scorer.score());
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if(comp.test(currentVal, nullCompVal)) {
          nullCompVal = currentVal;
          nullDoc = globalDoc;
          if(needsScores) {
            nullScore = scorer.score();
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if(needsScores) {
          nullScores.add(scorer.score());
        }
      }
    }
  }

  private static class IntFloatStrategy extends IntFieldValueStrategy {

    private final String field;
    private NumericDocValues minMaxVals;
    private IntFloatDynamicMap testValues;
    private FloatCompare comp;
    private float nullCompVal;

    private int index=-1;

    public IntFloatStrategy(int maxDoc,
                            int size,
                            String collapseField,
                            int nullValue,
                            int nullPolicy,
                            GroupHeadSelector groupHeadSelector,
                            boolean needsScores,
                            IntIntHashMap boostDocs) throws IOException {

      super(maxDoc, size, collapseField, nullValue, nullPolicy, needsScores, boostDocs);
      this.field = groupHeadSelector.selectorText;
      this.testValues = new IntFloatDynamicMap(size, 0.0f);

      assert GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type);

      if (GroupHeadSelectorType.MAX.equals(groupHeadSelector.type)) {
        comp = new MaxFloatComp();
        this.nullCompVal = -Float.MAX_VALUE;
      } else {
        comp = new MinFloatComp();
        this.nullCompVal = Float.MAX_VALUE;
      }
    }

    public void setNextReader(LeafReaderContext context) throws IOException {
      this.minMaxVals = DocValues.getNumeric(context.reader(), this.field);
    }

    public void collapse(int collapseKey, int contextDoc, int globalDoc) throws IOException {

      // Check to see if we have documents boosted by the QueryElevationComponent
      if(boosts && mergeBoost.boost(globalDoc)) {
        boostDocs.add(globalDoc);
        boostKeys.add(collapseKey);
        return;
      }

      int minMaxVal;
      if (minMaxVals.advanceExact(contextDoc)) {
        minMaxVal = (int) minMaxVals.longValue();
      } else {
        minMaxVal = 0;
      }

      float currentVal = Float.intBitsToFloat(minMaxVal);

      if(collapseKey != nullValue) {
        final int idx;
        if((idx = cmap.indexOf(collapseKey)) >= 0) {
          int pointer = cmap.indexGet(idx);
          if(comp.test(currentVal, testValues.get(pointer))) {
            testValues.put(pointer, currentVal);
            docs.put(pointer, globalDoc);
            if(needsScores) {
              scores.put(pointer, scorer.score());
            }
          }
        } else {
          ++index;
          cmap.put(collapseKey, index);
          testValues.put(index, currentVal);
          docs.put(index, globalDoc);
          if(needsScores) {
            scores.put(index, scorer.score());
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if(comp.test(currentVal, nullCompVal)) {
          nullCompVal = currentVal;
          nullDoc = globalDoc;
          if(needsScores) {
            nullScore = scorer.score();
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if(needsScores) {
          nullScores.add(scorer.score());
        }
      }
    }
  }

  /*
   *  Strategy for collapsing on a 32 bit numeric field and selecting the group head based
   *  on the min/max value of a Value Source Function.
   */
  private static class IntValueSourceStrategy extends IntFieldValueStrategy {

    private FloatCompare comp;
    private IntFloatDynamicMap testValues;
    private float nullCompVal;

    private ValueSource valueSource;
    private FunctionValues functionValues;
    @SuppressWarnings({"rawtypes"})
    private Map rcontext;
    private final CollapseScore collapseScore = new CollapseScore();
    private int index=-1;
    private boolean needsScores4Collapsing;

    public IntValueSourceStrategy(int maxDoc,
                                  int size,
                                  String collapseField,
                                  int nullValue,
                                  int nullPolicy,
                                  GroupHeadSelector groupHeadSelector,
                                  boolean needsScores4Collapsing,
                                  boolean needsScores,
                                  IntIntHashMap boostDocs,
                                  FunctionQuery funcQuery,
                                  IndexSearcher searcher) throws IOException {

      super(maxDoc, size, collapseField, nullValue, nullPolicy, needsScores, boostDocs);

      this.needsScores4Collapsing = needsScores4Collapsing;
      this.testValues = new IntFloatDynamicMap(size, 0.0f);

      this.valueSource = funcQuery.getValueSource();
      this.rcontext = ValueSource.newContext(searcher);

      assert GroupHeadSelectorType.MIN_MAX.contains(groupHeadSelector.type);

      if (GroupHeadSelectorType.MAX.equals(groupHeadSelector.type)) {
        this.nullCompVal = -Float.MAX_VALUE;
        comp = new MaxFloatComp();
      } else {
        this.nullCompVal = Float.MAX_VALUE;
        comp = new MinFloatComp();
      }

      collapseScore.setupIfNeeded(groupHeadSelector, rcontext);
    }

    @SuppressWarnings({"unchecked"})
    public void setNextReader(LeafReaderContext context) throws IOException {
      functionValues = this.valueSource.getValues(rcontext, context);
    }

    public void collapse(int collapseKey, int contextDoc, int globalDoc) throws IOException {
      float score = 0;

      // Check to see if we have documents boosted by the QueryElevationComponent
      if(boosts && mergeBoost.boost(globalDoc)) {
        boostDocs.add(globalDoc);
        boostKeys.add(collapseKey);
        return;
      }

      if (needsScores4Collapsing) {
        score = scorer.score();
        this.collapseScore.score = score;
      }

      float currentVal = functionValues.floatVal(contextDoc);

      if(collapseKey != nullValue) {
        final int idx;
        if((idx = cmap.indexOf(collapseKey)) >= 0) {
          int pointer = cmap.indexGet(idx);
          if(comp.test(currentVal, testValues.get(pointer))) {
            testValues.put(pointer, currentVal);
            docs.put(pointer, globalDoc);
            if(needsScores){
              if (!needsScores4Collapsing) {
                score = scorer.score();
              }
              scores.put(pointer, score);
            }
          }
        } else {
          ++index;
          cmap.put(collapseKey, index);
          docs.put(index, globalDoc);
          testValues.put(index, currentVal);
          if(needsScores) {
            if (!needsScores4Collapsing) {
              score = scorer.score();
            }
            scores.put(index, score);
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if(comp.test(currentVal, nullCompVal)) {
          nullCompVal = currentVal;
          nullDoc = globalDoc;
          if(needsScores) {
            if (!needsScores4Collapsing) {
              score = scorer.score();
            }
            nullScore = score;
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if(needsScores) {
          if (!needsScores4Collapsing) {
            score = scorer.score();
          }
          nullScores.add(score);
        }
      }
    }
  }


  /*
   * Strategy for collapsing on a 32 bit numeric field and using the first document according
   * to a complex sort as the group head
   */
  private static class IntSortSpecStrategy extends IntFieldValueStrategy {

    private final SortFieldsCompare compareState;
    private final SortSpec sortSpec;
    private final Sort sort;

    private int index=-1;
    private boolean needsScores4Collapsing;

    public IntSortSpecStrategy(int maxDoc,
                               int size,
                               String collapseField,
                               int nullValue,
                               int nullPolicy,
                               GroupHeadSelector groupHeadSelector,
                               boolean needsScores4Collapsing,
                               boolean needsScores,
                               IntIntHashMap boostDocs,
                               SortSpec sortSpec,
                               IndexSearcher searcher) throws IOException {

      super(maxDoc, size, collapseField, nullValue, nullPolicy, needsScores, boostDocs);
      this.needsScores4Collapsing = needsScores4Collapsing;

      assert GroupHeadSelectorType.SORT.equals(groupHeadSelector.type);

      this.sortSpec = sortSpec;
      this.sort = rewriteSort(sortSpec, searcher);
      this.compareState = new SortFieldsCompare(sort.getSort(), size);
    }

    @Override
    public void setNextReader(LeafReaderContext context) throws IOException {
      compareState.setNextReader(context);
    }

    @Override
    public void setScorer(Scorable s) throws IOException {
      super.setScorer(s);
      this.compareState.setScorer(s);
    }

    public void collapse(int collapseKey, int contextDoc, int globalDoc) throws IOException {
      float score = 0;

      // Check to see if we have documents boosted by the QueryElevationComponent
      if(boosts && mergeBoost.boost(globalDoc)) {
        boostDocs.add(globalDoc);
        boostKeys.add(collapseKey);
        return;
      }

      if (needsScores4Collapsing) {
        score = scorer.score();
      }

      if (collapseKey != nullValue) {
        final int idx;
        if ((idx = cmap.indexOf(collapseKey)) >= 0) {
          // we've seen this collapseKey before, test to see if it's a new group leader
          int pointer = cmap.indexGet(idx);
          if (compareState.testAndSetGroupValues(pointer, contextDoc)) {
            docs.put(pointer, globalDoc);
            if (needsScores) {
              if (!needsScores4Collapsing) {
                score = scorer.score();
              }
              scores.put(pointer, score);
            }
          }
        } else {
          // we've never seen this collapseKey before, treat it as group head for now
          ++index;
          cmap.put(collapseKey, index);
          docs.put(index, globalDoc);
          compareState.setGroupValues(index, contextDoc);
          if(needsScores) {
            if (!needsScores4Collapsing) {
              score = scorer.score();
            }
            scores.put(index, score);
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_COLLAPSE) {
        if (-1 == nullDoc) {
          // we've never seen a doc with null collapse key yet, treat it as the null group head for now
          compareState.setNullGroupValues(contextDoc);
          nullDoc = globalDoc;
          if (needsScores) {
            if (!needsScores4Collapsing) {
              score = scorer.score();
            }
            nullScore = score;
          }
        } else {
          // test this doc to see if it's the new null leader
          if (compareState.testAndSetNullGroupValues(contextDoc)) {
            nullDoc = globalDoc;
            if (needsScores) {
              if (!needsScores4Collapsing) {
                score = scorer.score();
              }
              nullScore = score;
            }
          }
        }
      } else if(this.nullPolicy == CollapsingPostFilter.NULL_POLICY_EXPAND) {
        this.collapsedSet.set(globalDoc);
        if (needsScores) {
          if (!needsScores4Collapsing) {
            score = scorer.score();
          }
          nullScores.add(score);
        }
      }
    }
  }

  static class MergeBoost {

    private int[] boostDocs;
    private int index = 0;

    public MergeBoost(int[] boostDocs) {
      this.boostDocs = boostDocs;
    }

    public void reset() {
      this.index = 0;
    }

    public boolean boost(int globalDoc) {
      if(index == Integer.MIN_VALUE) {
        return false;
      } else {
        while(true) {
          if(index >= boostDocs.length) {
            index = Integer.MIN_VALUE;
            return false;
          } else {
            int comp = boostDocs[index];
            if(comp == globalDoc) {
              ++index;
              return true;
            } else if(comp < globalDoc) {
              ++index;
            } else {
              return false;
            }
          }
        }
      }
    }
  }

  /**
   * Class for comparing documents according to a list of SortField clauses and
   * tracking the groupHeadLeaders and their sort values.  groups will be identified
   * by int "contextKey values, which may either be (encoded) 32bit numeric values, or
   * ordinal values for Strings -- this class doesn't care, and doesn't assume any special
   * meaning.
   */
  private static class SortFieldsCompare {
    final private int numClauses;
    final private SortField[] sorts;
    final private int[] reverseMul;
    @SuppressWarnings({"rawtypes"})
    final private FieldComparator[] fieldComparators;
    final private LeafFieldComparator[] leafFieldComparators;

    private Object[][] groupHeadValues; // growable
    final private Object[] nullGroupValues;

    /**
     * Constructs an instance based on the the (raw, un-rewritten) SortFields to be used,
     * and an initial number of expected groups (will grow as needed).
     */
    @SuppressWarnings({"rawtypes"})
    public SortFieldsCompare(SortField[] sorts, int initNumGroups) {
      this.sorts = sorts;
      numClauses = sorts.length;
      fieldComparators = new FieldComparator[numClauses];
      leafFieldComparators = new LeafFieldComparator[numClauses];
      reverseMul = new int[numClauses];
      for (int clause = 0; clause < numClauses; clause++) {
        SortField sf = sorts[clause];
        // we only need one slot for every comparator
        fieldComparators[clause] = sf.getComparator(1, clause);
        reverseMul[clause] = sf.getReverse() ? -1 : 1;
      }
      groupHeadValues = new Object[initNumGroups][];
      nullGroupValues = new Object[numClauses];
    }

    public void setNextReader(LeafReaderContext context) throws IOException {
      for (int clause = 0; clause < numClauses; clause++) {
        leafFieldComparators[clause] = fieldComparators[clause].getLeafComparator(context);
      }
    }
    public void setScorer(Scorable s) throws IOException {
      for (int clause = 0; clause < numClauses; clause++) {
        leafFieldComparators[clause].setScorer(s);
      }
    }

    // LUCENE-6808 workaround
    private static Object cloneIfBytesRef(Object val) {
      if (val instanceof BytesRef) {
        return BytesRef.deepCopyOf((BytesRef) val);
      }
      return val;
    }

    /**
     * Returns the current SortField values for the specified collapseKey.
     * If this collapseKey has never been seen before, then an array of null values is inited
     * and tracked so that the caller may update it if needed.
     */
    private Object[] getOrInitGroupHeadValues(int collapseKey) {
      Object[] values = groupHeadValues[collapseKey];
      if (null == values) {
        values = new Object[numClauses];
        groupHeadValues[collapseKey] = values;
      }
      return values;
    }

    /**
     * Records the SortField values for the specified contextDoc as the "best" values
     * for the group identified by the specified collapseKey.
     *
     * Should be called the first time a contextKey is encountered.
     */
    public void setGroupValues(int collapseKey, int contextDoc) throws IOException {
      assert 0 <= collapseKey : "negative collapseKey";
      if (collapseKey >= groupHeadValues.length) {
        grow(collapseKey + 1);
      }
      setGroupValues(getOrInitGroupHeadValues(collapseKey), contextDoc);
    }
    
    /**
     * Records the SortField values for the specified contextDoc as the "best" values 
     * for the null group.
     *
     * Should be calledthe first time a doc in the null group is encountered
     */
    public void setNullGroupValues(int contextDoc) throws IOException {
      setGroupValues(nullGroupValues, contextDoc);
    }
    
    /**
     * Records the SortField values for the specified contextDoc into the 
     * values array provided by the caller.
     */
    private void setGroupValues(Object[] values, int contextDoc) throws IOException {
      for (int clause = 0; clause < numClauses; clause++) {
        leafFieldComparators[clause].copy(0, contextDoc);
        values[clause] = cloneIfBytesRef(fieldComparators[clause].value(0));
      }
    }

    /**
     * Compares the SortField values of the specified contextDoc with the existing group head 
     * values for the group identified by the specified collapseKey, and overwrites them
     * (and returns true) if this document should become the new group head in accordance 
     * with the SortFields
     * (otherwise returns false)
     */
    public boolean testAndSetGroupValues(int collapseKey, int contextDoc) throws IOException {
      assert 0 <= collapseKey : "negative collapseKey";
      if (collapseKey >= groupHeadValues.length) {
        grow(collapseKey + 1);
      }
      return testAndSetGroupValues(getOrInitGroupHeadValues(collapseKey), contextDoc);
    }
    
    /**
     * Compares the SortField values of the specified contextDoc with the existing group head 
     * values for the null group, and overwrites them (and returns true) if this document 
     * should become the new group head in accordance with the SortFields. 
     * (otherwise returns false)
     */
    public boolean testAndSetNullGroupValues(int contextDoc) throws IOException {
      return testAndSetGroupValues(nullGroupValues, contextDoc);
    }

    /**
     * Compares the SortField values of the specified contextDoc with the existing values
     * array, and overwrites them (and returns true) if this document is the new group head in 
     * accordance with the SortFields.
     * (otherwise returns false)
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    private boolean testAndSetGroupValues(Object[] values, int contextDoc) throws IOException {
      Object[] stash = new Object[numClauses];
      int lastCompare = 0;
      int testClause = 0;
      for (/* testClause */; testClause < numClauses; testClause++) {
        leafFieldComparators[testClause].copy(0, contextDoc);
        FieldComparator fcomp = fieldComparators[testClause];
        stash[testClause] = cloneIfBytesRef(fcomp.value(0));
        lastCompare = reverseMul[testClause] * fcomp.compareValues(stash[testClause], values[testClause]);
        
        if (0 != lastCompare) {
          // no need to keep checking additional clauses
          break;
        }
      }

      if (0 <= lastCompare) {
        // we're either not competitive, or we're completely tied with another doc that's already group head
        // that's already been selected
        return false;
      } // else...
      
      // this doc is our new group head, we've already read some of the values into our stash
      testClause++;
      System.arraycopy(stash, 0, values, 0, testClause);
      // read the remaining values we didn't need to test
      for (int copyClause = testClause; copyClause < numClauses; copyClause++) {
        leafFieldComparators[copyClause].copy(0, contextDoc);
        values[copyClause] = cloneIfBytesRef(fieldComparators[copyClause].value(0));
      }
      return true;
    }

    /**
     * Grows all internal arrays to the specified minSize
     */
    public void grow(int minSize) {
      groupHeadValues = ArrayUtil.grow(groupHeadValues, minSize);
    }
  }
    
  private static interface IntCompare {
    public boolean test(int i1, int i2);
  }

  private static interface FloatCompare {
    public boolean test(float i1, float i2);
  }

  private static interface LongCompare {
    public boolean test(long i1, long i2);
  }

  private static class MaxIntComp implements IntCompare {
    public boolean test(int i1, int i2) {
      return i1 > i2;
    }
  }

  private static class MinIntComp implements IntCompare {
    public boolean test(int i1, int i2) {
      return i1 < i2;
    }
  }

  private static class MaxFloatComp implements FloatCompare {
    public boolean test(float i1, float i2) {
      return i1 > i2;
    }
  }

  private static class MinFloatComp implements FloatCompare {
    public boolean test(float i1, float i2) {
      return i1 < i2;
    }
  }

  private static class MaxLongComp implements LongCompare {
    public boolean test(long i1, long i2) {
      return i1 > i2;
    }
  }

  private static class MinLongComp implements LongCompare {
    public boolean test(long i1, long i2) {
      return i1 < i2;
    }
  }

  /** returns the number of arguments that are non null */
  private static final int numNotNull(final Object... args) {
    int r = 0;
    for (final Object o : args) {
      if (null != o) {
        r++;
      }
    }
    return r;
  }

  /**
   * Helper method for rewriting the Sort associated with a SortSpec.  
   * Handles the special case default of relevancy sort (ie: a SortSpec w/null Sort object)
   */
  public static Sort rewriteSort(SortSpec sortSpec, IndexSearcher searcher) throws IOException {
    assert null != sortSpec : "SortSpec must not be null";
    assert null != searcher : "Searcher must not be null";
    Sort orig = sortSpec.getSort();
    if (null == orig) {
      orig = Sort.RELEVANCE;
    }
    return orig.rewrite(searcher);
  }
}
