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

/*
 * Do not add dependency to java.awt.Rectangle2D in this class, because not every platforms
 * support Java2D (e.g. Android),  or applications that do not need it may want to avoid to
 * force installation of the Java2D module (e.g. JavaFX/SWT).
 */
import java.util.Arrays;
import java.util.Objects;
import java.io.Serializable;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.referencing.cs.RangeMeaning;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;

import static org.apache.sis.util.ArgumentChecks.*;
import static org.apache.sis.math.MathFunctions.isNegative;
import static org.apache.sis.internal.referencing.Formulas.isPoleToPole;


/**
 * Base class of envelopes backed by an array. The coordinate values are stored in the {@link #coordinates} array.
 * The coordinate values of the lower corner are stored in the array portion from index {@link #beginIndex()}
 * inclusive to index {@link #endIndex()} exclusive. The coordinate values of the upper corner are stored in
 * the array portion from index {@code beginIndex() + d} inclusive to index {@code endIndex() + d} exclusive
 * where {@code d = coordinates.length >>> 1}.
 *
 * <p>Unless otherwise indicated by a "{@code // Must be overridden in SubEnvelope}" comment, every methods
 * in {@code ArrayEnvelope} and subclasses must take in account the {@code beginIndex} and {@code endIndex}
 * bounds. A few methods ignore the bounds for performance reason, so they need a dedicated implementation
 * in {@link SubEnvelope}.</p>
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 1.0
 * @since   0.3
 * @module
 */
class ArrayEnvelope extends AbstractEnvelope implements Serializable {
    /**
     * Serial number for inter-operability with different versions.
     */
    private static final long serialVersionUID = 3685400961133848112L;

    /**
     * Coordinate values of lower and upper corners. Except for {@link SubEnvelope}, the length
     * of this array is twice the number of dimensions. The first half contains the lower corner,
     * while the second half contains the upper corner.
     */
    final double[] coordinates;

    /**
     * The coordinate reference system, or {@code null}.
     */
    CoordinateReferenceSystem crs;

    /**
     * Creates a new envelope using the given array of coordinate values. This constructor stores
     * the given reference directly; it does <strong>not</strong> clone the given array. This is
     * the desired behavior for proper working of {@link SubEnvelope}.
     *
     * @param  coordinates  the array of coordinate values to store directly (not cloned).
     */
    ArrayEnvelope(final double[] coordinates) {
        this.coordinates = coordinates;
    }

    /*
     * Constructors below this point have public access because if we decided to make class
     * ArrayEnvelope public, then we would probably want to make those constructors public too.
     */

    /**
     * Constructs an envelope defined by two corners given as direct positions.
     * If at least one corner is associated to a CRS, then the new envelope will also
     * be associated to that CRS.
     *
     * @param  lowerCorner  the limits in the direction of decreasing coordinate values for each dimension.
     * @param  upperCorner  the limits in the direction of increasing coordinate values for each dimension.
     * @throws MismatchedDimensionException if the two positions do not have the same dimension.
     * @throws MismatchedReferenceSystemException if the CRS of the two position are not equal.
     */
    public ArrayEnvelope(final DirectPosition lowerCorner, final DirectPosition upperCorner)
            throws MismatchedDimensionException, MismatchedReferenceSystemException
    {
        crs = getCommonCRS(lowerCorner, upperCorner);           // This performs also an argument check.
        final int dimension = lowerCorner.getDimension();
        ensureDimensionMatches("crs", dimension, crs);
        ensureSameDimension(dimension, upperCorner.getDimension());
        coordinates = new double[dimension * 2];
        for (int i=0; i<dimension; i++) {
            coordinates[i            ] = lowerCorner.getOrdinate(i);
            coordinates[i + dimension] = upperCorner.getOrdinate(i);
        }
        verifyRanges(crs, coordinates);
    }

    /**
     * Constructs an envelope defined by two corners given as sequences of coordinate values.
     * The Coordinate Reference System is initially {@code null}.
     *
     * @param  lowerCorner  the limits in the direction of decreasing coordinate values for each dimension.
     * @param  upperCorner  the limits in the direction of increasing coordinate values for each dimension.
     * @throws MismatchedDimensionException if the two sequences do not have the same length.
     */
    public ArrayEnvelope(final double[] lowerCorner, final double[] upperCorner) throws MismatchedDimensionException {
        ensureNonNull("lowerCorner", lowerCorner);
        ensureNonNull("upperCorner", upperCorner);
        ensureSameDimension(lowerCorner.length, upperCorner.length);
        coordinates = Arrays.copyOf(lowerCorner, lowerCorner.length + upperCorner.length);
        System.arraycopy(upperCorner, 0, coordinates, lowerCorner.length, upperCorner.length);
    }

    /**
     * Constructs an empty envelope of the specified dimension. All coordinates
     * are initialized to 0 and the coordinate reference system is undefined.
     *
     * @param  dimension  the envelope dimension.
     */
    public ArrayEnvelope(final int dimension) {
        coordinates = new double[dimension * 2];
    }

    /**
     * Constructs an empty envelope with the specified coordinate reference system.
     * All coordinate values are initialized to 0.
     *
     * @param  crs  the coordinate reference system.
     */
    public ArrayEnvelope(final CoordinateReferenceSystem crs) {
        ensureNonNull("crs", crs);
        coordinates = new double[crs.getCoordinateSystem().getDimension() * 2];
        this.crs = crs;
    }

    /**
     * Constructs a new envelope with the same data than the specified envelope.
     *
     * @param envelope  the envelope to copy.
     */
    public ArrayEnvelope(final Envelope envelope) {
        ensureNonNull("envelope", envelope);
        /*
         * Do not optimize with `if (envelope instanceof ArrayEnvelope)` because subclasses may change the semantic.
         * In particular the SubEnvelope subclass uses only a subrange of this array. If we still want to optimize,
         * we would have to test for specific classes. It is probably not worth at this stage.
         */
        crs = envelope.getCoordinateReferenceSystem();
        final int dimension = envelope.getDimension();
        coordinates = new double[dimension * 2];
        final DirectPosition lowerCorner = envelope.getLowerCorner();
        final DirectPosition upperCorner = envelope.getUpperCorner();
        for (int i=0; i<dimension; i++) {
            coordinates[i]           = lowerCorner.getOrdinate(i);
            coordinates[i+dimension] = upperCorner.getOrdinate(i);
        }
        verifyRanges(crs, coordinates);
    }

    /**
     * Constructs a new envelope with the same data than the specified geographic bounding box.
     * The coordinate reference system is set to the
     * {@linkplain org.apache.sis.referencing.CommonCRS#defaultGeographic() default geographic CRS}.
     * Axis order is (<var>longitude</var>, <var>latitude</var>).
     *
     * @param box  the bounding box to copy.
     */
    public ArrayEnvelope(final GeographicBoundingBox box) {
        ensureNonNull("box", box);
        coordinates = new double[] {
            box.getWestBoundLongitude(),
            box.getSouthBoundLatitude(),
            box.getEastBoundLongitude(),
            box.getNorthBoundLatitude()
        };
        if (Boolean.FALSE.equals(box.getInclusion())) {
            ArraysExt.swap(coordinates, 0, coordinates.length >>> 1);
            if (!isPoleToPole(coordinates[1], coordinates[3])) {
                ArraysExt.swap(coordinates, 1, (coordinates.length >>> 1) + 1);
            }
        }
        crs = CommonCRS.defaultGeographic();
        verifyRanges(crs, coordinates);
    }

    /**
     * Constructs a new envelope initialized to the values parsed from the given string in
     * {@code BOX} or <cite>Well Known Text</cite> (WKT) format. The given string is typically
     * a {@code BOX} element like below:
     *
     * {@preformat wkt
     *     BOX(-180 -90, 180 90)
     * }
     *
     * However this constructor is lenient to other geometry types like {@code POLYGON}.
     * See the javadoc of the {@link GeneralEnvelope#GeneralEnvelope(CharSequence) GeneralEnvelope}
     * constructor for more information.
     *
     * @param  wkt  the {@code BOX}, {@code POLYGON} or other kind of element to parse.
     * @throws IllegalArgumentException if the given string can not be parsed.
     */
    public ArrayEnvelope(final CharSequence wkt) throws IllegalArgumentException {
        ensureNonNull("wkt", wkt);
        int levelParenth = 0;               // Number of opening parenthesis: (
        int levelBracket = 0;               // Number of opening brackets: [
        int dimLimit     = 4;               // The length of minimum and maximum arrays.
        int maxDimension = 0;               // The number of valid entries in the minimum and maximum arrays.
        final int length = CharSequences.skipTrailingWhitespaces(wkt, 0, wkt.length());
        double[] minimum = new double[dimLimit];
        double[] maximum = new double[dimLimit];
        int dimension = 0;
        int c;
scan:   for (int i=CharSequences.skipLeadingWhitespaces(wkt, 0, length); i<length; i+=Character.charCount(c)) {
            c = Character.codePointAt(wkt, i);
            if (Character.isUnicodeIdentifierStart(c)) {
                do {
                    i += Character.charCount(c);
                    if (i >= length) break scan;
                    c = Character.codePointAt(wkt, i);
                }
                while (Character.isUnicodeIdentifierPart(c));
            }
            if (Character.isSpaceChar(c)) {
                continue;
            }
            switch (c) {
                case ',':                                      dimension=0; continue;
                case '(':     ++levelParenth;                  dimension=0; continue;
                case '[':     ++levelBracket;                  dimension=0; continue;
                case ')': if (--levelParenth<0) fail(wkt,'('); dimension=0; continue;
                case ']': if (--levelBracket<0) fail(wkt,'['); dimension=0; continue;
            }
            /*
             * At this point we have skipped the leading keyword (BOX, POLYGON, etc.),
             * the spaces and the parenthesis if any. We should be at the beginning of
             * a number. Search the first separator character (which determine the end
             * of the number) and parse the number.
             */
            final int start = i;
            boolean flush = false;
scanNumber: while ((i += Character.charCount(c)) < length) {
                c = wkt.charAt(i);
                if (Character.isSpaceChar(c)) {
                    break;
                }
                switch (c) {
                    case ',':                                      flush=true; break scanNumber;
                    case ')': if (--levelParenth<0) fail(wkt,'('); flush=true; break scanNumber;
                    case ']': if (--levelBracket<0) fail(wkt,'['); flush=true; break scanNumber;
                }
            }
            /*
             * Parsing the number may throw a NumberFormatException. But the later is an
             * IllegalArgumentException subclass, so we are compliant with the contract.
             */
            final double value = Double.parseDouble(wkt.subSequence(start, i).toString());
            /*
             * Adjust the minimum and maximum value using the number that we parsed,
             * increasing the arrays size if necessary. Remember the maximum number
             * of dimensions we have found so far.
             */
            if (dimension == maxDimension) {
                if (dimension == dimLimit) {
                    dimLimit *= 2;
                    minimum = Arrays.copyOf(minimum, dimLimit);
                    maximum = Arrays.copyOf(maximum, dimLimit);
                }
                minimum[dimension] = maximum[dimension] = value;
                maxDimension = ++dimension;
            } else {
                if (value < minimum[dimension]) minimum[dimension] = value;
                if (value > maximum[dimension]) maximum[dimension] = value;
                dimension++;
            }
            if (flush) {
                dimension = 0;
            }
        }
        if (levelParenth != 0) fail(wkt, ')');
        if (levelBracket != 0) fail(wkt, ']');
        coordinates = ArraysExt.resize(minimum, maxDimension << 1);
        System.arraycopy(maximum, 0, coordinates, maxDimension, maxDimension);
    }

    /**
     * Throws an exception for unmatched parenthesis during WKT parsing.
     */
    private static void fail(final CharSequence wkt, char missing) {
        throw new IllegalArgumentException(Errors.format(
                Errors.Keys.NonEquilibratedParenthesis_2, wkt, missing));
    }

    /**
     * Makes sure the specified dimensions are identical.
     */
    static void ensureSameDimension(final int dim1, final int dim2) throws MismatchedDimensionException {
        if (dim1 != dim2) {
            throw new MismatchedDimensionException(Errors.format(
                    Errors.Keys.MismatchedDimension_2, dim1, dim2));
        }
    }

    /**
     * Verifies the validity of the range of coordinates values in the given array.
     * If the given CRS is null, then this method conservatively does nothing.
     * Otherwise this method performs the following verifications:
     *
     * <ul>
     *   <li>{@code lower > upper} is allowed only for axes having {@link RangeMeaning#WRAPAROUND}.</li>
     * </ul>
     *
     * This method does <strong>not</strong> verify if the coordinate values are between the axis minimum and
     * maximum values. This is because out-of-range values exist in practice but do not impact the working
     * of {@code add(…)}, {@code intersect(…)}, {@code contains(…)} and similar methods. This in contrast
     * with the checks listed above, where failure to met those conditions will cause the methods to
     * behave in an unexpected way.
     *
     * <div class="section">Implementation consistency</div>
     * The checks performed by this method shall be consistent with the checks performed by the following methods:
     * <ul>
     *   <li>{@link GeneralEnvelope#setCoordinateReferenceSystem(CoordinateReferenceSystem)}</li>
     *   <li>{@link GeneralEnvelope#setRange(int, double, double)}</li>
     *   <li>{@link SubEnvelope#setRange(int, double, double)}</li>
     * </ul>
     *
     * @param  crs          the coordinate reference system, or {@code null}.
     * @param  coordinates  the array of coordinate values to verify.
     */
    static void verifyRanges(final CoordinateReferenceSystem crs, final double[] coordinates) {
        if (crs != null) {
            final int dimension = coordinates.length >>> 1;
            for (int i=0; i<dimension; i++) {
                final double lower = coordinates[i];
                final double upper = coordinates[i + dimension];
                if (lower > upper && !isWrapAround(crs, i)) {
                    throw new IllegalArgumentException(illegalRange(crs, i, lower, upper));
                }
            }
        }
    }

    /**
     * Creates an error message for an illegal coordinates range at the given dimension.
     * This is used for formatting the exception message.
     */
    static String illegalRange(final CoordinateReferenceSystem crs,
            final int dimension, final double lower, final double upper)
    {
        Object name = IdentifiedObjects.getName(getAxis(crs, dimension), null);
        if (name == null) {
            name = dimension;       // Paranoiac fallback (name should never be null).
        }
        return Errors.format(Errors.Keys.IllegalCoordinateRange_3, lower, upper, name);
    }

    /**
     * Returns the index of the first valid coordinate value of the lower corner in the {@link #coordinates} array.
     * This is always 0, unless this envelope is a {@link SubEnvelope}.
     *
     * <p>See {@link #endIndex()} for the list of methods that need to be also overridden
     * if this {@code beginIndex()} method is overridden.</p>
     */
    int beginIndex() {
        return 0;
    }

    /**
     * Returns the index after the last valid coordinate value of the lower corner in the {@link #coordinates} array.
     * This is always {@code coordinates.length >>> 1}, unless this envelope is a {@link SubEnvelope}.
     *
     * <p>Unless otherwise indicated by a "{@code // Must be overridden in SubEnvelope}" comment, every methods
     * in {@code ArrayEnvelope} and subclasses must take in account the {@code beginIndex} and {@code endIndex}
     * bounds. The methods listed below ignore the bounds for performance reason, so they need to be overridden
     * in {@link SubEnvelope}:</p>
     *
     * <ul>
     *   <li>{@link #getDimension()}</li>
     *   <li>{@link #getLower(int)}</li>
     *   <li>{@link #getUpper(int)}</li>
     *   <li>{@link #isAllNaN()}</li>
     *   <li>{@link #hashCode()}</li>
     *   <li>{@link #equals(Object)}</li>
     * </ul>
     */
    int endIndex() {
        return coordinates.length >>> 1;
    }

    /**
     * Returns the length of coordinate sequence (the number of entries) in this envelope.
     * This information is available even when the {@linkplain #getCoordinateReferenceSystem()
     * coordinate reference system} is unknown.
     *
     * @return the dimensionality of this envelope.
     */
    @Override                                       // Must also be overridden in SubEnvelope
    public int getDimension() {
        return coordinates.length >>> 1;
    }

    /**
     * Returns the envelope coordinate reference system, or {@code null} if unknown.
     * If non-null, it shall be the same as {@linkplain #getLowerCorner() lower corner}
     * and {@linkplain #getUpperCorner() upper corner} CRS.
     *
     * @return the envelope CRS, or {@code null} if unknown.
     */
    @Override
    public CoordinateReferenceSystem getCoordinateReferenceSystem() {
        assert crs == null || crs.getCoordinateSystem().getDimension() == getDimension();
        return crs;
    }

    /**
     * {@inheritDoc}
     */
    @Override                                       // Must also be overridden in SubEnvelope
    public double getLower(final int dimension) throws IndexOutOfBoundsException {
        ensureValidIndex(coordinates.length >>> 1, dimension);
        return coordinates[dimension];
    }

    /**
     * {@inheritDoc}
     */
    @Override                                       // Must also be overridden in SubEnvelope
    public double getUpper(final int dimension) throws IndexOutOfBoundsException {
        final int d = coordinates.length >>> 1;
        ensureValidIndex(d, dimension);
        return coordinates[dimension + d];
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double getMinimum(final int dimension) throws IndexOutOfBoundsException {
        ensureValidIndex(endIndex(), dimension);
        final int i = dimension + beginIndex();
        double lower = coordinates[i];
        if (isNegative(coordinates[i + (coordinates.length >>> 1)] - lower)) {    // Special handling for -0.0
            final CoordinateSystemAxis axis = getAxis(crs, dimension);
            lower = isWrapAround(axis) ? axis.getMinimumValue() : Double.NaN;
        }
        return lower;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double getMaximum(final int dimension) throws IndexOutOfBoundsException {
        ensureValidIndex(endIndex(), dimension);
        final int i = dimension + beginIndex();
        double upper = coordinates[i + (coordinates.length >>> 1)];
        if (isNegative(upper - coordinates[i])) {                               // Special handling for -0.0
            final CoordinateSystemAxis axis = getAxis(crs, dimension);
            upper = isWrapAround(axis) ? axis.getMaximumValue() : Double.NaN;
        }
        return upper;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double getMedian(final int dimension) throws IndexOutOfBoundsException {
        ensureValidIndex(endIndex(), dimension);
        final int i = dimension + beginIndex();
        final double minimum = coordinates[i];
        final double maximum = coordinates[i + (coordinates.length >>> 1)];
        double median = 0.5 * (minimum + maximum);
        if (isNegative(maximum - minimum)) {                                    // Special handling for -0.0
            median = fixMedian(getAxis(crs, dimension), median);
        }
        return median;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double getSpan(final int dimension) throws IndexOutOfBoundsException {
        ensureValidIndex(endIndex(), dimension);
        final int i = dimension + beginIndex();
        double span = coordinates[i + (coordinates.length >>> 1)] - coordinates[i];
        if (isNegative(span)) {                                                 // Special handling for -0.0
            span = fixSpan(getAxis(crs, dimension), span);
        }
        return span;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isEmpty() {
        final int beginIndex = beginIndex();
        final int endIndex = endIndex();
        if (beginIndex == endIndex) {
            return true;
        }
        final int d = coordinates.length >>> 1;
        for (int i=beginIndex; i<endIndex; i++) {
            final double span = coordinates[i+d] - coordinates[i];
            if (!(span > 0)) {                                                  // Use '!' in order to catch NaN
                if (!(isNegative(span) && isWrapAround(crs, i - beginIndex))) {
                    return true;
                }
            }
        }
        assert !isAllNaN() : this;
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override                                       // Must also be overridden in SubEnvelope
    public boolean isAllNaN() {
        for (int i=0; i<coordinates.length; i++) {
            if (!Double.isNaN(coordinates[i])) {
                return false;
            }
        }
        assert isEmpty() : this;
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override                                       // Must also be overridden in SubEnvelope
    public int hashCode() {
        int code = Arrays.hashCode(coordinates);
        if (crs != null) {
            code += crs.hashCode();
        }
        assert code == hashCodeByAPI();
        return code;
    }

    /**
     * Computes the hash code value using the public API instead than direct access to the
     * {@link #coordinates} array. This method is invoked from {@link SubEnvelope}.
     */
    final int hashCodeByAPI() {
        return super.hashCode();
    }

    /**
     * {@inheritDoc}
     */
    @Override                                       // Must also be overridden in SubEnvelope
    public boolean equals(final Object object) {
        if (object != null && object.getClass() == getClass()) {
            final ArrayEnvelope that = (ArrayEnvelope) object;
            return Arrays.equals(this.coordinates, that.coordinates) &&
                  Objects.equals(this.crs, that.crs);
        }
        return false;
    }

    /**
     * Compares the given object for equality using the public API instead than direct access
     * to the {@link #coordinates} array. This method is invoked from {@link SubEnvelope}.
     */
    final boolean equalsByAPI(final Object object) {
        return super.equals(object);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return toString(this, ArraysExt.isSinglePrecision(coordinates));
    }
}
