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

import java.util.Locale;
import java.util.Formatter;
import java.util.Formattable;
import java.util.FormattableFlags;
import java.text.Format;
import java.text.ParseException;
import java.io.Serializable;
import javax.measure.Unit;
import javax.measure.IncommensurableException;
import org.opengis.geometry.DirectPosition;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.internal.util.Strings;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.Classes;

import static java.lang.Double.doubleToLongBits;
import static org.apache.sis.math.MathFunctions.isNegative;


/**
 * An angle in decimal degrees. An angle is the amount of rotation needed to bring one line or plane
 * into coincidence with another. Various kind of angles are used in geographic information systems,
 * some of them having a specialized class in Apache SIS:
 *
 * <ul>
 *   <li>{@linkplain Latitude} is an angle ranging from 0° at the equator to 90° at the poles.</li>
 *   <li>{@linkplain Longitude} is an angle measured east-west from a prime meridian (usually Greenwich, but not necessarily).</li>
 *   <li><cite>Azimuth</cite> is a direction given by an angle between 0° and 360° measured clockwise from North.</li>
 *   <li><cite>Bearing</cite> is a direction given by an angle between 0° and 90° in a quadrant defined by a cardinal direction.</li>
 *   <li><cite>Bearing</cite> is also sometime used in navigation for an angle relative to the vessel forward direction.</li>
 *   <li><cite>Deflection angle</cite> is the angle between a line and the prolongation of a preceding line.</li>
 *   <li><cite>Interior angle</cite> is an angle measured between two lines of sight.</li>
 *   <li>{@linkplain ElevationAngle Elevation angle} is the angular height from the horizontal plane to an object above the horizon.</li>
 * </ul>
 *
 * <h2>Formatting angles</h2>
 * The recommended way to format angles is to instantiate an {@link AngleFormat} once, then to
 * reuse it many times. As a convenience, {@code Angle} objects can also be formatted by the
 * {@code "%s"} conversion specifier of {@link Formatter}, but this is less efficient for this
 * class.
 *
 * <h2>Immutability and thread safety</h2>
 * This class and the {@link Latitude} / {@link Longitude} subclasses are immutable, and thus
 * inherently thread-safe. Other subclasses may or may not be immutable, at implementation choice
 * (see {@link java.lang.Number} for an example of a similar in purpose class having mutable subclasses).
 *
 * @author  Martin Desruisseaux (MPO, IRD, Geomatys)
 * @version 0.8
 *
 * @see Latitude
 * @see Longitude
 * @see AngleFormat
 *
 * @since 0.3
 * @module
 */
public class Angle implements Comparable<Angle>, Formattable, Serializable {
    /**
     * Serial number for inter-operability with different versions.
     */
    private static final long serialVersionUID = 3701568577051191744L;

    /**
     * A shared instance of {@link AngleFormat}.
     *
     * @see #getAngleFormat()
     */
    private static Format format;

    /**
     * Angle value in decimal degrees. We use decimal degrees as the storage unit
     * instead than radians in order to avoid rounding errors, since there is no
     * way to represent 30°, 45°, 90°, 180°, <i>etc.</i> in radians without errors.
     */
    private final double θ;

    /**
     * Constructs a new angle with the specified value in decimal degrees.
     *
     * @param  θ  angle in decimal degrees.
     */
    public Angle(final double θ) {
        this.θ = θ;
    }

    /**
     * Constructs a newly allocated {@code Angle} object that contain the angular value
     * represented by the string. The string should represent an angle in either fractional
     * degrees (e.g. 45.5°) or degrees with minutes and seconds (e.g. 45°30').
     *
     * <p>This is a convenience constructor mostly for testing purpose, since it uses a fixed
     * locale. Developers should consider using {@link AngleFormat} for end-user applications
     * instead than this constructor.</p>
     *
     * @param  text  a string to be converted to an {@code Angle}.
     * @throws NumberFormatException if the string does not contain a parsable angle.
     *
     * @see AngleFormat#parse(String)
     */
    public Angle(final String text) throws NumberFormatException {
        final Object angle;
        try {
            synchronized (Angle.class) {
                angle = getAngleFormat().parseObject(text);
            }
        } catch (ParseException exception) {
            /*
             * Use Exception.getMessage() instead than getLocalizedMessage() because the later
             * is formatted in the AngleFormat locale, which is hard-coded to Locale.ROOT in our
             * 'getAngleFormat()' implementation. The getMessage() method uses the system locale,
             * which is what we actually want.
             */
            throw (NumberFormatException) new NumberFormatException(exception.getMessage()).initCause(exception);
        }
        final Class<?> type = angle.getClass();
        if (type == Angle.class || getClass().isAssignableFrom(type)) {
            this.θ = ((Angle) angle).θ;
        } else {
            throw new NumberFormatException(text);
        }
    }

    /**
     * Returns the angular value of the axis having the given direction.
     * This helper method is used for subclass constructors expecting a {@link DirectPosition} argument.
     *
     * @param  position  the position from which to get an angular value.
     * @param  positive  axis direction of positive values.
     * @param  negative  axis direction of negative values.
     * @return angular value in degrees.
     * @throws IllegalArgumentException if the given coordinate it not associated to a CRS,
     *         or if no axis oriented toward the given directions is found, or if that axis
     *         does not use {@linkplain Units#isAngular angular units}.
     */
    static double valueOf(final DirectPosition position, final AxisDirection positive, final AxisDirection negative) {
        final CoordinateReferenceSystem crs = position.getCoordinateReferenceSystem();
        if (crs == null) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.UnspecifiedCRS));
        }
        final CoordinateSystem cs = crs.getCoordinateSystem();
        final int dimension = cs.getDimension();
        IncommensurableException cause = null;
        for (int i=0; i<dimension; i++) {
            final CoordinateSystemAxis axis = cs.getAxis(i);
            final AxisDirection dir = axis.getDirection();
            final boolean isPositive = dir.equals(positive);
            if (isPositive || dir.equals(negative)) {
                double value = position.getOrdinate(i);
                if (!isPositive) value = -value;
                final Unit<?> unit = axis.getUnit();
                if (unit != Units.DEGREE) try {
                    value = unit.getConverterToAny(Units.DEGREE).convert(value);
                } catch (IncommensurableException e) {
                    cause = e;
                    break;
                }
                return value;
            }
        }
        throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalCRSType_1,
                Classes.getLeafInterfaces(crs.getClass(), CoordinateReferenceSystem.class)[0]), cause);
    }

    /**
     * Returns the angle value in decimal degrees.
     *
     * @return the angle value in decimal degrees.
     */
    public double degrees() {
        return θ;
    }

    /**
     * Returns the angle value in radians.
     *
     * @return the angle value in radians.
     */
    public double radians() {
        return Math.toRadians(θ);
    }

    /**
     * Returns a hash code for this {@code Angle} object.
     */
    @Override
    public int hashCode() {
        final long code = Double.doubleToLongBits(θ);
        return (int) code ^ (int) (code >>> 32) ^ (int) serialVersionUID;
    }

    /**
     * Compares the specified object with this angle for equality.
     *
     * @param  object  the object to compare with this angle for equality.
     * @return {@code true} if the given object is equal to this angle.
     */
    @Override
    public boolean equals(final Object object) {
        if (object == this) {
            return true;
        }
        if (object != null && getClass() == object.getClass()) {
            return doubleToLongBits(θ) == doubleToLongBits(((Angle) object).θ);
        }
        return false;
    }

    /**
     * Compares two {@code Angle} objects numerically. The comparison
     * is done as if by the {@link Double#compare(double, double)} method.
     *
     * @param  that  the angle to compare with this object for order.
     * @return -1 if this angle is smaller than the given one, +1 if greater or 0 if equals.
     */
    @Override
    public int compareTo(final Angle that) {
        return Double.compare(this.θ, that.θ);
    }

    /**
     * Upper threshold before to format an angle as an ordinary number.
     * This is set to 90° in the case of latitude numbers.
     */
    double maximum() {
        return 360;
    }

    /**
     * Returns the hemisphere character for an angle of the given sign.
     * This is used only by {@link #toString()}, not by {@link AngleFormat}.
     */
    char hemisphere(final boolean negative) {
        return 0;
    }

    /**
     * Returns a string representation of this {@code Angle} object.
     * This is a convenience method mostly for debugging purpose, since it uses a fixed locale.
     * Developers should consider using {@link AngleFormat} for end-user applications instead
     * than this method.
     *
     * @see AngleFormat#format(double)
     */
    @Override
    public String toString() {
        StringBuffer buffer = new StringBuffer();
        double m = Math.abs(θ);
        final boolean isSmall = m <= (1 / 3600E+3);                     // 1E-3 arc-second.
        if ((isSmall || m > maximum()) && m != 0) {
            final char h = hemisphere(isNegative(θ));
            if (h == 0) {
                m = θ;                                                  // Restore the sign.
            }
            char symbol = '°';
            if (isSmall) {
                symbol = '″';
                m *= 3600;
            }
            buffer.append(m).append(symbol);
            if (h != 0) {
                buffer.append(h);
            }
        } else {
            synchronized (Angle.class) {
                buffer = getAngleFormat().format(this, buffer, null);
            }
        }
        return buffer.toString();
    }

    /**
     * Returns a shared instance of {@link AngleFormat}. The return type is
     * {@link Format} in order to avoid class loading before necessary.
     *
     * <p>This method must be invoked in a {@code synchronized(Angle.class)} block. We use
     * synchronization instead than static class initialization because {@code AngleFormat}
     * is not thread-safe, so it needs to be used in a synchronized block anyway. We could
     * avoid synchronization by using {@link ThreadLocal}, but this brings other issues in
     * OSGi context. Given that our Javadoc said that {@link #Angle(String)} and {@link #toString()}
     * should be used mostly for debugging purpose, we consider not worth to ensure high
     * concurrency capability here.</p>
     */
    private static Format getAngleFormat() {
        assert Thread.holdsLock(Angle.class);
        if (format == null) {
            format = new AngleFormat(Locale.ROOT);
        }
        return format;
    }

    /**
     * Formats this angle using the provider formatter. This method is invoked when an
     * {@code Angle} object is formatted using the {@code "%s"} conversion specifier of
     * {@link Formatter}. Users don't need to invoke this method explicitly.
     *
     * <p>Special cases:</p>
     * <ul>
     *   <li>If the precision is 0, then this method formats an empty string.</li>
     *   <li>If the precision is 1 and this angle is a {@link Latitude} or {@link Longitude},
     *       then this method formats only the hemisphere symbol.</li>
     *   <li>Otherwise the precision, if positive, is given to {@link AngleFormat#setMaximumWidth(int)}.</li>
     * </ul>
     *
     * @param  formatter  the formatter in which to format this angle.
     * @param  flags      {@link FormattableFlags#LEFT_JUSTIFY} for left alignment, or 0 for right alignment.
     * @param  width      minimal number of characters to write, padding with {@code ' '} if necessary.
     * @param  precision  maximal number of characters to write, or -1 if no limit.
     */
    @Override
    public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) {
        final String value;
        if (precision == 0) {
            value = "";
        } else {
            final char h;
            int w = precision;      // To be decremented only if we may truncate and an hemisphere symbol exist.
            if (w > 0 && (h = hemisphere(isNegative(θ))) != 0 && --w == 0) {
                value = Character.toString(h);
            } else {
                final AngleFormat format = new AngleFormat(formatter.locale());
                if (w > 0) {
                    format.setMaximumWidth(w);
                }
                value = format.format(this, new StringBuffer(), null).toString();
            }
        }
        Strings.formatTo(formatter, flags, width, precision, value);
    }
}
