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

import java.util.Map;
import java.util.Objects;
import javax.measure.Unit;
import javax.measure.quantity.Angle;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.opengis.util.GenericName;
import org.opengis.util.InternationalString;
import org.opengis.referencing.ReferenceIdentifier;
import org.opengis.referencing.datum.PrimeMeridian;
import org.opengis.referencing.crs.GeneralDerivedCRS;
import org.apache.sis.referencing.AbstractIdentifiedObject;
import org.apache.sis.internal.referencing.Formulas;
import org.apache.sis.internal.referencing.WKTUtilities;
import org.apache.sis.internal.referencing.ReferencingUtilities;
import org.apache.sis.internal.metadata.MetadataUtilities;
import org.apache.sis.internal.referencing.WKTKeywords;
import org.apache.sis.internal.jaxb.gml.Measure;
import org.apache.sis.internal.util.Numerics;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.io.wkt.Convention;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.measure.Units;

import static org.apache.sis.util.ArgumentChecks.ensureFinite;
import static org.apache.sis.util.ArgumentChecks.ensureNonNull;


/**
 * Defines the origin from which longitude values are determined.
 *
 * <h2>Creating new prime meridian instances</h2>
 * New instances can be created either directly by specifying all information to a factory method (choices 3
 * and 4 below), or indirectly by specifying the identifier of an entry in a database (choices 1 and 2 below).
 * In particular, the <a href="http://www.epsg.org">EPSG</a> database provides definitions for many prime meridians,
 * and Apache SIS provides convenience shortcuts for some of them.
 *
 * <p>Choice 1 in the following list is the easiest but most restrictive way to get a prime meridian.
 * The other choices provide more freedom. Each choice delegates its work to the subsequent items
 * (in the default configuration), so this list can been seen as <cite>top to bottom</cite> API.</p>
 *
 * <ol>
 *   <li>Create a {@code PrimeMeridian} from one of the static convenience shortcuts listed in
 *       {@link org.apache.sis.referencing.CommonCRS#primeMeridian()}.</li>
 *   <li>Create a {@code PrimeMeridian} from an identifier in a database by invoking
 *       {@link org.opengis.referencing.datum.DatumAuthorityFactory#createPrimeMeridian(String)}.</li>
 *   <li>Create a {@code PrimeMeridian} by invoking the {@code DatumFactory.createPrimeMeridian(…)} method
 *       (implemented for example by {@link org.apache.sis.referencing.factory.GeodeticObjectFactory}).</li>
 *   <li>Create a {@code DefaultPrimeMeridian} by invoking the
 *       {@linkplain #DefaultPrimeMeridian(Map, double, Unit) constructor}.</li>
 * </ol>
 *
 * <b>Example:</b> the following code gets the Greenwich prime meridian:
 *
 * {@preformat java
 *     PrimeMeridian pm = CommonCRS.WGS84.primeMeridian();
 * }
 *
 * <h2>Immutability and thread safety</h2>
 * This class is immutable and thus thread-safe if the property <em>values</em> (not necessarily the map itself)
 * given to the constructor are also immutable. Unless otherwise noted in the javadoc, this condition holds if
 * all components were created using only SIS factories and static constants.
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @author  Cédric Briançon (Geomatys)
 * @version 0.7
 *
 * @see org.apache.sis.referencing.CommonCRS#primeMeridian()
 * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createPrimeMeridian(String)
 *
 * @since 0.4
 * @module
 */
@XmlType(name = "PrimeMeridianType")
@XmlRootElement(name = "PrimeMeridian")
public class DefaultPrimeMeridian extends AbstractIdentifiedObject implements PrimeMeridian {
    /**
     * Serial number for inter-operability with different versions.
     */
    private static final long serialVersionUID = 541978454643213305L;;

    /**
     * Longitude of the prime meridian measured from the Greenwich meridian, positive eastward.
     *
     * <p><b>Consider this field as final!</b>
     * This field is modified only at unmarshalling time by {@link #setGreenwichMeasure(Measure)}</p>
     */
    private double greenwichLongitude;

    /**
     * The angular unit of the {@linkplain #getGreenwichLongitude() Greenwich longitude}.
     *
     * <p><b>Consider this field as final!</b>
     * This field is modified only at unmarshalling time by {@link #setGreenwichMeasure(Measure)}</p>
     */
    private Unit<Angle> angularUnit;

    /**
     * Creates a prime meridian from the given properties. The properties map is given unchanged to the
     * {@linkplain AbstractIdentifiedObject#AbstractIdentifiedObject(Map) super-class constructor}.
     * The following table is a reminder of main (not all) properties:
     *
     * <table class="sis">
     *   <caption>Recognized properties (non exhaustive list)</caption>
     *   <tr>
     *     <th>Property name</th>
     *     <th>Value type</th>
     *     <th>Returned by</th>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.referencing.IdentifiedObject#NAME_KEY}</td>
     *     <td>{@link ReferenceIdentifier} or {@link String}</td>
     *     <td>{@link #getName()}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.referencing.IdentifiedObject#ALIAS_KEY}</td>
     *     <td>{@link GenericName} or {@link CharSequence} (optionally as array)</td>
     *     <td>{@link #getAlias()}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY}</td>
     *     <td>{@link ReferenceIdentifier} (optionally as array)</td>
     *     <td>{@link #getIdentifiers()}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY}</td>
     *     <td>{@link InternationalString} or {@link String}</td>
     *     <td>{@link #getRemarks()}</td>
     *   </tr>
     * </table>
     *
     * @param  properties          the properties to be given to the identified object.
     * @param  greenwichLongitude  the longitude value relative to the Greenwich Meridian.
     * @param  angularUnit         the angular unit of the longitude.
     *
     * @see org.apache.sis.referencing.factory.GeodeticObjectFactory#createPrimeMeridian(Map, double, Unit)
     */
    public DefaultPrimeMeridian(final Map<String,?> properties, final double greenwichLongitude,
                                final Unit<Angle> angularUnit)
    {
        super(properties);
        ensureFinite("greenwichLongitude", greenwichLongitude);
        ensureNonNull("angularUnit", angularUnit);
        this.greenwichLongitude = greenwichLongitude;
        this.angularUnit = angularUnit;
    }

    /**
     * Creates a new prime meridian with the same values than the specified one.
     * This copy constructor provides a way to convert an arbitrary implementation into a SIS one
     * or a user-defined one (as a subclass), usually in order to leverage some implementation-specific API.
     *
     * <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
     *
     * @param  meridian  the prime meridian to copy.
     *
     * @see #castOrCopy(PrimeMeridian)
     */
    protected DefaultPrimeMeridian(final PrimeMeridian meridian) {
        super(meridian);
        greenwichLongitude = meridian.getGreenwichLongitude();
        angularUnit        = meridian.getAngularUnit();
    }

    /**
     * Returns a SIS prime meridian implementation with the same values than the given arbitrary implementation.
     * If the given object is {@code null}, then this method returns {@code null}.
     * Otherwise if the given object is already a SIS implementation, then the given object is returned unchanged.
     * Otherwise a new SIS implementation is created and initialized to the attribute values of the given object.
     *
     * @param  object  the object to get as a SIS implementation, or {@code null} if none.
     * @return a SIS implementation containing the values of the given object (may be the
     *         given object itself), or {@code null} if the argument was null.
     */
    public static DefaultPrimeMeridian castOrCopy(final PrimeMeridian object) {
        return (object == null) || (object instanceof DefaultPrimeMeridian)
                ? (DefaultPrimeMeridian) object : new DefaultPrimeMeridian(object);
    }

    /**
     * Returns the GeoAPI interface implemented by this class.
     * The SIS implementation returns {@code PrimeMeridian.class}.
     *
     * <div class="note"><b>Note for implementers:</b>
     * Subclasses usually do not need to override this method since GeoAPI does not define {@code PrimeMeridian}
     * sub-interface. Overriding possibility is left mostly for implementers who wish to extend GeoAPI with their
     * own set of interfaces.</div>
     *
     * @return {@code PrimeMeridian.class} or a user-defined sub-interface.
     */
    @Override
    public Class<? extends PrimeMeridian> getInterface() {
        return PrimeMeridian.class;
    }

    /**
     * Longitude of the prime meridian measured from the Greenwich meridian, positive eastward.
     *
     * @return the prime meridian Greenwich longitude, in {@linkplain #getAngularUnit() angular unit}.
     */
    @Override
    public double getGreenwichLongitude() {
        return greenwichLongitude;
    }

    /**
     * Returns the longitude value relative to the Greenwich Meridian, expressed in the specified units.
     * This convenience method makes it easier to obtain longitude in decimal degrees using the following
     * code, regardless of the underlying angular units of this prime meridian:
     *
     * {@preformat java
     *     double longitudeInDegrees = primeMeridian.getGreenwichLongitude(Units.DEGREE);
     * }
     *
     * @param  unit  the unit in which to express longitude.
     * @return the Greenwich longitude in the given units.
     */
    public double getGreenwichLongitude(final Unit<Angle> unit) {
        return getAngularUnit().getConverterTo(unit).convert(getGreenwichLongitude());
    }

    /**
     * Returns the angular unit of the Greenwich longitude.
     *
     * @return the angular unit of the {@linkplain #getGreenwichLongitude() Greenwich longitude}.
     */
    @Override
    public Unit<Angle> getAngularUnit() {
        return angularUnit;
    }

    /**
     * Compares this prime meridian with the specified object for equality.
     *
     * @param  object  the object to compare to {@code this}.
     * @param  mode {@link ComparisonMode#STRICT STRICT} for performing a strict comparison, or
     *         {@link ComparisonMode#IGNORE_METADATA IGNORE_METADATA} for comparing only properties
     *         relevant to coordinate transformations.
     * @return {@code true} if both objects are equal.
     */
    @Override
    public boolean equals(final Object object, final ComparisonMode mode) {
        if (object == this) {
            return true;                                // Slight optimization.
        }
        if (super.equals(object, mode)) switch (mode) {
            case STRICT: {
                final DefaultPrimeMeridian that = (DefaultPrimeMeridian) object;
                return Numerics.equals(this.greenwichLongitude, that.greenwichLongitude) &&
                        Objects.equals(this.angularUnit,        that.angularUnit);
            }
            case BY_CONTRACT: {
                final PrimeMeridian that = (PrimeMeridian) object;
                return Numerics.equals(getGreenwichLongitude(), that.getGreenwichLongitude()) &&
                        Objects.equals(getAngularUnit(),        that.getAngularUnit());
            }
            default: {
                final double v1 = getGreenwichLongitude(Units.DEGREE);
                final double v2 = ReferencingUtilities.getGreenwichLongitude((PrimeMeridian) object, Units.DEGREE);
                if (mode == ComparisonMode.IGNORE_METADATA) {
                    /*
                     * We relax the check on unit of measurement because EPSG uses sexagesimal degrees
                     * for the Greenwich meridian.  Requirying the same unit would make more difficult
                     * for isWGS84(…) methods to recognize EPSG's WGS84. We allow this relaxation here
                     * because the unit of the prime meridian is usually not inherited by axes (indeed,
                     * they are often not the same in the EPSG dataset). The same is not true for other
                     * objects like DefaultEllipsoid.
                     */
                    return Numerics.equals(v1, v2);
                } else if (Numerics.epsilonEqual(v1, v2, Formulas.ANGULAR_TOLERANCE)) {
                    return true;
                }
                assert (mode != ComparisonMode.DEBUG) : Numerics.messageForDifference("greenwichLongitude", v1, v2);
            }
        }
        return false;
    }

    /**
     * Invoked by {@code hashCode()} for computing the hash code when first needed.
     * See {@link org.apache.sis.referencing.AbstractIdentifiedObject#computeHashCode()}
     * for more information.
     *
     * @return the hash code value. This value may change in any future Apache SIS version.
     */
    @Override
    protected long computeHashCode() {
        return super.computeHashCode() + Double.doubleToLongBits(greenwichLongitude) + Objects.hashCode(angularUnit);
    }

    /**
     * Returns {@code true} if the given formatter is in the process of formatting the prime meridian of a base CRS
     * of an {@code AbstractDerivedCRS}. In such case, base CRS coordinate system axes shall not be formatted, which
     * has the consequence of bringing the {@code UNIT[…]} element right below the {@code PRIMEM[…]} one. Example:
     *
     * {@preformat wkt
     *   ProjectedCRS[“NTF (Paris) / Lambert zone II”,
     *     BaseGeodCRS[“NTF (Paris)”,
     *       Datum[“Nouvelle Triangulation Francaise”,
     *         Ellipsoid[“NTF”, 6378249.2, 293.4660212936269]],
     *       PrimeMeridian[“Paris”, 2.5969213],
     *       AngleUnit[“grad”, 0.015707963267948967]],
     *     Conversion[“Lambert zone II”,
     *       etc...
     * }
     *
     * If we were not formatting a base CRS, we would have many lines between {@code PrimeMeridian[…]} and
     * {@code AngleUnit[…]} in the above example, which would make less obvious that the angle unit applies
     * also to the prime meridian. It does not bring any ambiguity from an ISO 19162 standard point of view,
     * but historically some other software products interpreted the {@code PRIMEM[…]} units wrongly, which
     * is why we try to find a compromise between keeping the WKT simple and avoiding an historical ambiguity.
     *
     * @see org.apache.sis.referencing.crs.AbstractCRS#isBaseCRS(Formatter)
     */
    private static boolean isElementOfBaseCRS(final Formatter formatter) {
        return formatter.getEnclosingElement(2) instanceof GeneralDerivedCRS;
    }

    /**
     * Returns {@code true} if {@link #formatTo(Formatter)} should conservatively format the angular unit
     * even if it would be legal to omit it.
     *
     * <h4>Rational</h4>
     * According the ISO 19162 standard, it is legal to omit the {@code PrimeMeridian} angular unit when
     * that unit is the same than the unit of the axes of the enclosing {@code GeographicCRS}. However the
     * relationship between the CRS axes and the prime meridian is less obvious in WKT2 than it was in WKT1,
     * because the WKT2 {@code UNIT[…]} element is far from the {@code PRIMEM[…]} element while it was just
     * below it in WKT1.   Furthermore, the {@code PRIMEM[…]} unit is one source of incompatibility between
     * various WKT1 parsers (i.e. some popular libraries are not conform to OGC 01-009 and ISO 19162).
     * So we are safer to unconditionally format any unit other than degrees, even if we could legally
     * omit them.
     *
     * <p>However in order to keep the WKT slightly simpler in {@link Convention#WKT2_SIMPLIFIED} mode,
     * we make an exception to the above-cited safety if the {@code UNIT[…]} element is formatted right
     * below the {@code PRIMEM[…]} one, which happen if we are inside a base CRS.
     * See {@link #isElementOfBaseCRS(Formatter)} for more discussion.
     */
    private static boolean beConservative(final Formatter formatter, final Unit<Angle> contextualUnit) {
        return !contextualUnit.equals(Units.DEGREE) && !isElementOfBaseCRS(formatter);
    }

    /**
     * Formats this prime meridian as a <cite>Well Known Text</cite> {@code PrimeMeridian[…]} element.
     *
     * @return {@code "PrimeMeridian"} (WKT 2) or {@code "PrimeM"} (WKT 1).
     *
     * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#53">WKT 2 specification §8.2.2</a>
     */
    @Override
    protected String formatTo(final Formatter formatter) {
        super.formatTo(formatter);
        final Convention  convention = formatter.getConvention();
        final boolean     isWKT1 = (convention.majorVersion() == 1);
        final Unit<Angle> contextualUnit = formatter.toContextualUnit(Units.DEGREE);
        Unit<Angle> unit = contextualUnit;
        if (!isWKT1) {
            unit = getAngularUnit();
            if (convention != Convention.INTERNAL) {
                unit = WKTUtilities.toFormattable(unit);
            }
        }
        formatter.append(getGreenwichLongitude(unit));
        if (isWKT1) {
            return WKTKeywords.PrimeM;
        }
        if (!convention.isSimplified() || !contextualUnit.equals(unit) || beConservative(formatter, contextualUnit)) {
            formatter.append(unit);
        }
        return formatter.shortOrLong(WKTKeywords.PrimeM, WKTKeywords.PrimeMeridian);
    }




    //////////////////////////////////////////////////////////////////////////////////////////////////
    ////////                                                                                  ////////
    ////////                               XML support with JAXB                              ////////
    ////////                                                                                  ////////
    ////////        The following methods are invoked by JAXB using reflection (even if       ////////
    ////////        they are private) or are helpers for other methods invoked by JAXB.       ////////
    ////////        Those methods can be safely removed if Geographic Markup Language         ////////
    ////////        (GML) support is not needed.                                              ////////
    ////////                                                                                  ////////
    //////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Constructs a new object in which every attributes are set to a null value.
     * <strong>This is not a valid object.</strong> This constructor is strictly
     * reserved to JAXB, which will assign values to the fields using reflexion.
     */
    private DefaultPrimeMeridian() {
        super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
        /*
         * Angular units are mandatory for SIS working. We do not verify their presence here (because the
         * verification would have to be done in an 'afterMarshal(…)' method and throwing an exception in
         * that method causes the whole unmarshalling to fail). But the CD_PrimeMeridian adapter does some
         * verifications.
         */
    }

    /**
     * Invoked by JAXB for obtaining the Greenwich longitude to marshal together with its {@code "uom"} attribute.
     */
    @XmlElement(name = "greenwichLongitude", required = true)
    private Measure getGreenwichMeasure() {
        return new Measure(greenwichLongitude, angularUnit);
    }

    /**
     * Invoked by JAXB for setting the Greenwich longitude and its unit of measurement.
     */
    private void setGreenwichMeasure(final Measure measure) {
        if (greenwichLongitude == 0 && angularUnit == null) {
            greenwichLongitude = measure.value;
            angularUnit = measure.getUnit(Angle.class);
            if (angularUnit == null) {
                /*
                 * Missing unit: if the Greenwich longitude is zero, any angular unit gives the same result
                 * (assuming that the missing unit was not applying an offset), so we can select a default.
                 * If the Greenwich longitude is not zero, presume egrees but log a warning.
                 */
                angularUnit = Units.DEGREE;
                if (greenwichLongitude != 0) {
                    Measure.missingUOM(DefaultPrimeMeridian.class, "setGreenwichMeasure");
                }
            }
        } else {
            MetadataUtilities.propertyAlreadySet(DefaultPrimeMeridian.class, "setGreenwichMeasure", "greenwichLongitude");
        }
    }
}
