/*
 * 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.lucene.spatial3d.geom;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

/**
 * This GeoBBox represents an area rectangle limited only in latitude.
 *
 * @lucene.internal
 */
class GeoLatitudeZone extends GeoBaseBBox {
  /** The top latitude of the zone */
  protected final double topLat;
  /** The bottom latitude of the zone */
  protected final double bottomLat;
  /** Cosine of the top lat */
  protected final double cosTopLat;
  /** Cosine of the bottom lat */
  protected final double cosBottomLat;
  /** The top plane */
  protected final SidedPlane topPlane;
  /** The bottom plane */
  protected final SidedPlane bottomPlane;
  /** An interior point */
  protected final GeoPoint interiorPoint;
  /** Notable points (none) */
  protected final static GeoPoint[] planePoints = new GeoPoint[0];

  // We need two additional points because a latitude zone's boundaries don't intersect.  This is a very
  // special case that most GeoBBox's do not have.
  
  /** Top boundary point */
  protected final GeoPoint topBoundaryPoint;
  /** Bottom boundary point */
  protected final GeoPoint bottomBoundaryPoint;
  /** A point on each distinct edge */
  protected final GeoPoint[] edgePoints;

  /** Constructor.
   *@param planetModel is the planet model to use.
   *@param topLat is the top latitude.
   *@param bottomLat is the bottom latitude.
   */
  public GeoLatitudeZone(final PlanetModel planetModel, final double topLat, final double bottomLat) {
    super(planetModel);
    this.topLat = topLat;
    this.bottomLat = bottomLat;

    final double sinTopLat = Math.sin(topLat);
    final double sinBottomLat = Math.sin(bottomLat);
    this.cosTopLat = Math.cos(topLat);
    this.cosBottomLat = Math.cos(bottomLat);

    // Compute an interior point.  Pick one whose lat is between top and bottom.
    final double middleLat = (topLat + bottomLat) * 0.5;
    final double sinMiddleLat = Math.sin(middleLat);
    this.interiorPoint = new GeoPoint(planetModel, sinMiddleLat, 0.0, Math.sqrt(1.0 - sinMiddleLat * sinMiddleLat), 1.0);
    this.topBoundaryPoint = new GeoPoint(planetModel, sinTopLat, 0.0, Math.sqrt(1.0 - sinTopLat * sinTopLat), 1.0);
    this.bottomBoundaryPoint = new GeoPoint(planetModel, sinBottomLat, 0.0, Math.sqrt(1.0 - sinBottomLat * sinBottomLat), 1.0);

    this.topPlane = new SidedPlane(interiorPoint, planetModel, sinTopLat);
    this.bottomPlane = new SidedPlane(interiorPoint, planetModel, sinBottomLat);

    this.edgePoints = new GeoPoint[]{topBoundaryPoint, bottomBoundaryPoint};
  }

  /**
   * Constructor for deserialization.
   * @param planetModel is the planet model.
   * @param inputStream is the input stream.
   */
  public GeoLatitudeZone(final PlanetModel planetModel, final InputStream inputStream) throws IOException {
    this(planetModel, SerializableObject.readDouble(inputStream), SerializableObject.readDouble(inputStream));
  }

  @Override
  public void write(final OutputStream outputStream) throws IOException {
    SerializableObject.writeDouble(outputStream, topLat);
    SerializableObject.writeDouble(outputStream, bottomLat);
  }

  @Override
  public GeoBBox expand(final double angle) {
    final double newTopLat = topLat + angle;
    final double newBottomLat = bottomLat - angle;
    return GeoBBoxFactory.makeGeoBBox(planetModel, newTopLat, newBottomLat, -Math.PI, Math.PI);
  }

  @Override
  public boolean isWithin(final double x, final double y, final double z) {
    return topPlane.isWithin(x, y, z) &&
        bottomPlane.isWithin(x, y, z);
  }

  @Override
  public double getRadius() {
    // This is a bit tricky.  I guess we should interpret this as meaning the angle of a circle that
    // would contain all the bounding box points, when starting in the "center".
    if (topLat > 0.0 && bottomLat < 0.0)
      return Math.PI;
    double maxCosLat = cosTopLat;
    if (maxCosLat < cosBottomLat)
      maxCosLat = cosBottomLat;
    return maxCosLat * Math.PI;
  }

  @Override
  public GeoPoint getCenter() {
    // This is totally arbitrary and only a cartesian could agree with it.
    return interiorPoint;
  }

  @Override
  public GeoPoint[] getEdgePoints() {
    return edgePoints;
  }

  @Override
  public boolean intersects(final Plane p, final GeoPoint[] notablePoints, final Membership... bounds) {
    return p.intersects(planetModel, topPlane, notablePoints, planePoints, bounds, bottomPlane) ||
        p.intersects(planetModel, bottomPlane, notablePoints, planePoints, bounds, topPlane);
  }

  @Override
  public boolean intersects(final GeoShape geoShape) {
    return geoShape.intersects(topPlane, planePoints, bottomPlane) ||
        geoShape.intersects(bottomPlane, planePoints, topPlane);
  }

  @Override
  public void getBounds(Bounds bounds) {
    super.getBounds(bounds);
    bounds.noLongitudeBound()
      .addHorizontalPlane(planetModel, topLat, topPlane)
      .addHorizontalPlane(planetModel, bottomLat, bottomPlane);
  }

  @Override
  protected double outsideDistance(final DistanceStyle distanceStyle, final double x, final double y, final double z) {
    final double topDistance = distanceStyle.computeDistance(planetModel, topPlane, x,y,z, bottomPlane);
    final double bottomDistance = distanceStyle.computeDistance(planetModel, bottomPlane, x,y,z, topPlane);

    return Math.min(topDistance, bottomDistance);
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof GeoLatitudeZone))
      return false;
    GeoLatitudeZone other = (GeoLatitudeZone) o;
    return super.equals(other) && other.topBoundaryPoint.equals(topBoundaryPoint) && other.bottomBoundaryPoint.equals(bottomBoundaryPoint);
  }

  @Override
  public int hashCode() {
    int result = super.hashCode();
    result = 31 * result + topBoundaryPoint.hashCode();
    result = 31 * result + bottomBoundaryPoint.hashCode();
    return result;
  }

  @Override
  public String toString() {
    return "GeoLatitudeZone: {planetmodel="+planetModel+", toplat=" + topLat + "(" + topLat * 180.0 / Math.PI + "), bottomlat=" + bottomLat + "(" + bottomLat * 180.0 / Math.PI + ")}";
  }
}
