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

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.VectorValueSource;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.SortField;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.response.TextResponseWriter;
import org.apache.solr.search.QParser;
import org.apache.solr.search.SpatialOptions;
import org.apache.solr.uninverting.UninvertingReader.Type;
import org.locationtech.spatial4j.distance.DistanceUtils;

/**
 * A point type that indexes a point in an n-dimensional space as separate fields and supports range queries.
 * See {@link LatLonType} for geo-spatial queries.
 */
public class PointType extends CoordinateFieldType implements SpatialQueryable {

  @Override
  protected void init(IndexSchema schema, Map<String, String> args) {
    SolrParams p = new MapSolrParams(args);
    dimension = p.getInt(DIMENSION, DEFAULT_DIMENSION);
    if (dimension < 1) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
              "The dimension must be > 0: " + dimension);
    }
    args.remove(DIMENSION);
    super.init(schema, args);

    // cache suffixes
    createSuffixCache(dimension);
  }


  @Override
  public boolean isPolyField() {
    return true;   // really only true if the field is indexed
  }

  @Override
  public List<IndexableField> createFields(SchemaField field, Object value) {
    String externalVal = value.toString();
    String[] point = parseCommaSeparatedList(externalVal, dimension);

    // TODO: this doesn't currently support polyFields as sub-field types
    List<IndexableField> f = new ArrayList<>((dimension*2)+1);

    if (field.indexed()) {
      for (int i=0; i<dimension; i++) {
        SchemaField sf = subField(field, i, schema);
        f.addAll(sf.createFields(point[i]));
      }
    }

    if (field.stored()) {
      String storedVal = externalVal;  // normalize or not?
      f.add(createField(field.getName(), storedVal, StoredField.TYPE));
    }

    return f;
  }

  @Override
  public ValueSource getValueSource(SchemaField field, QParser parser) {
    ArrayList<ValueSource> vs = new ArrayList<>(dimension);
    for (int i=0; i<dimension; i++) {
      SchemaField sub = subField(field, i, schema);
      vs.add(sub.getType().getValueSource(sub, parser));
    }
    return new PointTypeValueSource(field, vs);
  }


  /**
   * It never makes sense to create a single field, so make it impossible to happen by
   * throwing UnsupportedOperationException
   *
   */
  @Override
  public IndexableField createField(SchemaField field, Object value) {
    throw new UnsupportedOperationException("PointType uses multiple fields.  field=" + field.getName());
  }

  @Override
  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
    writer.writeStr(name, f.stringValue(), true);
  }

  @Override
  public SortField getSortField(SchemaField field, boolean top) {
    throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Sorting not supported on PointType " + field.getName());
  }
  
  @Override
  public Type getUninversionType(SchemaField sf) {
    return null;
  }

  @Override
  /**
   * Care should be taken in calling this with higher order dimensions for performance reasons.
   */
  protected Query getSpecializedRangeQuery(QParser parser, SchemaField field, String part1, String part2, boolean minInclusive, boolean maxInclusive) {
    //Query could look like: [x1,y1 TO x2,y2] for 2 dimension, but could look like: [x1,y1,z1 TO x2,y2,z2], and can be extrapolated to n-dimensions
    //thus, this query essentially creates a box, cube, etc.
    String[] p1 = parseCommaSeparatedList(part1, dimension);
    String[] p2 = parseCommaSeparatedList(part2, dimension);

    BooleanQuery.Builder result = new BooleanQuery.Builder();
    for (int i = 0; i < dimension; i++) {
      SchemaField subSF = subField(field, i, schema);
      // points must currently be ordered... should we support specifying any two opposite corner points?
      result.add(subSF.getType().getRangeQuery(parser, subSF, p1[i], p2[i], minInclusive, maxInclusive), BooleanClause.Occur.MUST);
    }
    return result.build();
  }

  @Override
  public Query getFieldQuery(QParser parser, SchemaField field, String externalVal) {
    String[] p1 = parseCommaSeparatedList(externalVal, dimension);
    //TODO: should we assert that p1.length == dimension?
    BooleanQuery.Builder bq = new BooleanQuery.Builder();
    for (int i = 0; i < dimension; i++) {
      SchemaField sf = subField(field, i, schema);
      Query tq = sf.getType().getFieldQuery(parser, sf, p1[i]);
      bq.add(tq, BooleanClause.Occur.MUST);
    }
    return bq.build();
  }
  
  @Override
  protected void checkSupportsDocValues() {
    // DocValues supported only when enabled at the fieldType 
    if (!hasProperty(DOC_VALUES)) {
      throw new UnsupportedOperationException("PointType can't have docValues=true in the field definition, use docValues=true in the fieldType definition, or in subFieldType/subFieldSuffix");
    }
  }

  /**
   * Calculates the range and creates a RangeQuery (bounding box) wrapped in a BooleanQuery (unless the dimension is
   * 1, one range for every dimension, AND'd together by a Boolean
   *
   * @param parser  The parser
   * @param options The {@link org.apache.solr.search.SpatialOptions} for this filter.
   * @return The Query representing the bounding box around the point.
   */
  @Override
  public Query createSpatialQuery(QParser parser, SpatialOptions options) {
    String[] pointStrs = parseCommaSeparatedList(options.pointStr, dimension);
    double[] point = new double[dimension];
    try {
      for (int i = 0; i < pointStrs.length; i++) {
        point[i] = Double.parseDouble(pointStrs[i]);
      }
    } catch (NumberFormatException e) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
    }
    IndexSchema schema = parser.getReq().getSchema();

    if (dimension == 1){
      //TODO: Handle distance measures
      String lower = String.valueOf(point[0] - options.distance);
      String upper = String.valueOf(point[0] + options.distance);
      SchemaField subSF = subField(options.field, 0, schema);
      // points must currently be ordered... should we support specifying any two opposite corner points?
      return subSF.getType().getRangeQuery(parser, subSF, lower, upper, true, true);
    } else {
      BooleanQuery.Builder tmp = new BooleanQuery.Builder();
      //TODO: Handle distance measures, as this assumes Euclidean
      double[] ur = vectorBoxCorner(point, null, options.distance, true);
      double[] ll = vectorBoxCorner(point, null, options.distance, false);
      for (int i = 0; i < ur.length; i++) {
        SchemaField subSF = subField(options.field, i, schema);
        Query range = subSF.getType().getRangeQuery(parser, subSF, String.valueOf(ll[i]), String.valueOf(ur[i]), true, true);
        tmp.add(range, BooleanClause.Occur.MUST);
      }
      return tmp.build();
    }
  }

  private static final double SIN_PI_DIV_4 = Math.sin(Math.PI / 4);

  /**
   * Return the coordinates of a vector that is the corner of a box (upper right or lower left), assuming a Rectangular
   * coordinate system.  Note, this does not apply for points on a sphere or ellipse (although it could be used as an
   * approximation).
   *
   * @param center     The center point
   * @param result     Holds the result, potentially resizing if needed.
   * @param distance   The d from the center to the corner
   * @param upperRight If true, return the coords for the upper right corner, else return the lower left.
   * @return The point, either the upperLeft or the lower right
   */
  public static double[] vectorBoxCorner(double[] center, double[] result, double distance, boolean upperRight) {
    if (result == null || result.length != center.length) {
      result = new double[center.length];
    }
    if (upperRight == false) {
      distance = -distance;
    }
    //We don't care about the power here,
    // b/c we are always in a rectangular coordinate system, so any norm can be used by
    //using the definition of sine
    distance = SIN_PI_DIV_4 * distance; // sin(Pi/4) == (2^0.5)/2 == opp/hyp == opp/distance, solve for opp, similarly for cosine
    for (int i = 0; i < center.length; i++) {
      result[i] = center[i] + distance;
    }
    return result;
  }

  /**
   * Given a string containing <i>dimension</i> values encoded in it, separated by commas,
   * return a String array of length <i>dimension</i> containing the values.
   *
   * @param externalVal The value to parse
   * @param dimension   The expected number of values for the point
   * @return An array of the values that make up the point (aka vector)
   * @throws SolrException if the dimension specified does not match the number found
   */
  public static String[] parseCommaSeparatedList(String externalVal, int dimension) throws SolrException {
    //TODO: Should we support sparse vectors?
    String[] out = new String[dimension];
    int idx = externalVal.indexOf(',');
    int end = idx;
    int start = 0;
    int i = 0;
    if (idx == -1 && dimension == 1 && externalVal.length() > 0) {//we have a single point, dimension better be 1
      out[0] = externalVal.trim();
      i = 1;
    } else if (idx > 0) {//if it is zero, that is an error
      //Parse out a comma separated list of values, as in: 73.5,89.2,7773.4
      for (; i < dimension; i++) {
        while (start < end && externalVal.charAt(start) == ' ') start++;
        while (end > start && externalVal.charAt(end - 1) == ' ') end--;
        if (start == end) {
          break;
        }
        out[i] = externalVal.substring(start, end);
        start = idx + 1;
        end = externalVal.indexOf(',', start);
        idx = end;
        if (end == -1) {
          end = externalVal.length();
        }
      }
    }
    if (i != dimension) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
          "incompatible dimension (" + dimension +
              ") and values (" + externalVal + ").  Only " + i + " values specified");
    }
    return out;
  }

  @Override
  public double getSphereRadius() {
    // This won't likely be used. You should probably be using LatLonType instead if you felt the need for this.
    // This is here just for backward compatibility reasons.
    return DistanceUtils.EARTH_MEAN_RADIUS_KM;
  }

}


class PointTypeValueSource extends VectorValueSource {
  private final SchemaField sf;
  
  public PointTypeValueSource(SchemaField sf, List<ValueSource> sources) {
    super(sources);
    this.sf = sf;
  }

  @Override
  public String name() {
    return "point";
  }

  @Override
  public String description() {
    return name()+"("+sf.getName()+")";
  }
}
