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

import java.util.Set;
import java.util.LinkedHashSet;
import java.util.ServiceLoader;
import javax.measure.Unit;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.datum.DatumAuthorityFactory;
import org.opengis.referencing.datum.PrimeMeridian;
import org.opengis.referencing.datum.Ellipsoid;
import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.datum.VerticalDatum;
import org.opengis.referencing.crs.GeocentricCRS;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.crs.VerticalCRS;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CSAuthorityFactory;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.cs.SphericalCS;
import org.opengis.referencing.cs.CartesianCS;
import org.opengis.metadata.citation.Citation;
import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
import org.apache.sis.referencing.operation.provider.TransverseMercator;
import org.apache.sis.referencing.internal.Resources;
import org.apache.sis.system.Fallback;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Debug;
import org.apache.sis.util.privy.MetadataServices;
import org.apache.sis.util.privy.Constants;
import org.apache.sis.util.privy.URLs;
import org.apache.sis.setup.InstallationResources;
import org.apache.sis.measure.Latitude;
import org.apache.sis.measure.Units;


/**
 * The authority factory to use as a fallback when the real EPSG factory is not available.
 * We use this factory in order to guarantee that the minimal set of CRS codes documented
 * in the {@link CRS#forCode(String)} method javadoc is always available.
 * This fallback uses data available in public sources, with all EPSG metadata omitted except the identifiers.
 * The EPSG identifiers are provided as references where to find the complete definitions.
 *
 * @author  Martin Desruisseaux (Geomatys)
 */
@Fallback
final class EPSGFactoryFallback extends GeodeticAuthorityFactory
        implements CRSAuthorityFactory, CSAuthorityFactory, DatumAuthorityFactory
{
    /**
     * Whether to disallow {@code CommonCRS} to use {@link org.apache.sis.referencing.factory.sql.EPSGFactory}
     * (in which case {@code CommonCRS} will fallback on hard-coded values).
     * This field should always be {@code false}, except for debugging purposes.
     */
    @Debug
    static final boolean FORCE_HARDCODED = false;

    /**
     * The singleton instance.
     */
    static final EPSGFactoryFallback INSTANCE = new EPSGFactoryFallback();

    /**
     * URL  where users can get more information about the installation process.
     * Fetched when first needed.
     *
     * @see #getInstallationURL()
     * @see <a href="https://issues.apache.org/jira/browse/SIS-336">SIS-336</a>
     */
    private String installationURL;

    /**
     * Constructor for the singleton instance.
     */
    private EPSGFactoryFallback() {
    }

    /**
     * Returns an authority with "Subset of EPSG" title.
     */
    @Override
    public Citation getAuthority() {
        return StandardDefinitions.AUTHORITY;
    }

    /**
     * Returns the title of the authority as a string in the default locale.
     * This is used in exceptions.
     */
    private String getAuthorityTitle() {
        return getAuthority().getTitle().toString();
    }

    /**
     * Returns the namespace of EPSG codes.
     *
     * @return the {@code "EPSG"} string in a singleton map.
     */
    @Override
    public Set<String> getCodeSpaces() {
        return Set.of(Constants.EPSG);
    }

    /**
     * Returns the list of EPSG codes available.
     */
    @Override
    public Set<String> getAuthorityCodes(Class<? extends IdentifiedObject> type) {
        final boolean pm         = type.isAssignableFrom(PrimeMeridian.class);
        final boolean ellipsoid  = type.isAssignableFrom(Ellipsoid    .class);
        final boolean datum      = type.isAssignableFrom(GeodeticDatum.class);
        final boolean geographic = type.isAssignableFrom(GeographicCRS.class);
        final boolean geocentric = type.isAssignableFrom(GeocentricCRS.class);
        final boolean projected  = type.isAssignableFrom(ProjectedCRS .class);
        final Set<String> codes = new LinkedHashSet<>();
        if (pm) codes.add(StandardDefinitions.GREENWICH);
        for (final CommonCRS crs : CommonCRS.values()) {
            if (ellipsoid)  add(codes, crs.ellipsoid);
            if (datum)      add(codes, crs.datum);
            if (geocentric) add(codes, crs.geocentric);
            if (geographic) {
                add(codes, crs.geographic);
                add(codes, crs.geo3D);
            }
            if (projected) {
                add(codes, crs.northUPS);
                add(codes, crs.southUPS);
                if (crs.northUTM != 0 || crs.southUTM != 0) {
                    for (int zone = crs.firstZone; zone <= crs.lastZone; zone++) {
                        if (crs.northUTM != 0) codes.add(Integer.toString(crs.northUTM + zone));
                        if (crs.southUTM != 0) codes.add(Integer.toString(crs.southUTM + zone));
                    }
                }
            }
        }
        final boolean vertical = type.isAssignableFrom(VerticalCRS  .class);
        final boolean vdatum   = type.isAssignableFrom(VerticalDatum.class);
        if (vertical || vdatum) {
            for (final CommonCRS.Vertical candidate : CommonCRS.Vertical.values()) {
                if (candidate.isEPSG) {
                    if (vertical) add(codes, candidate.crs);
                    if (vdatum)   add(codes, candidate.datum);
                }
            }
        }
        if (type.isAssignableFrom(EllipsoidalCS.class)) {
            add(codes, StandardDefinitions.ELLIPSOIDAL_2D);
            add(codes, StandardDefinitions.ELLIPSOIDAL_3D);
        }
        if (type.isAssignableFrom(SphericalCS.class)) {
            add(codes, StandardDefinitions.SPHERICAL);
        }
        if (type.isAssignableFrom(CartesianCS.class)) {
            add(codes, StandardDefinitions.EARTH_CENTRED);
            add(codes, StandardDefinitions.CARTESIAN_2D);
            add(codes, StandardDefinitions.UPS_NORTH);
            add(codes, StandardDefinitions.UPS_SOUTH);
        }
        if (type.isAssignableFrom(Unit.class)) {
            add(codes, Constants.EPSG_METRE);
            add(codes, Constants.EPSG_AXIS_DEGREES);
        }
        return codes;
    }

    /**
     * Adds the given value to the given set, provided that the value is different than zero.
     * Zero is used as a sentinel value in {@link CommonCRS} meaning "no EPSG code".
     */
    private static void add(final Set<String> codes, final short value) {
        if (value != 0) codes.add(Short.toString(value));
    }

    /**
     * Kinds of object created by this factory, as bitmask. Note that objects
     * created for {@link #CS} and {@link #AXIS} kinds are currently not cached.
     */
    private static final int CRS=0x1, DATUM=0x2, ELLIPSOID=0x4, PRIME_MERIDIAN=0x8, UNIT=0x10, AXIS=0x20, CS=0x40;

    /**
     * Returns a prime meridian for the given EPSG code.
     */
    @Override
    public PrimeMeridian createPrimeMeridian(final String code) throws NoSuchAuthorityCodeException {
        return (PrimeMeridian) predefined(code, PRIME_MERIDIAN);
    }

    /**
     * Returns an ellipsoid for the given EPSG code.
     */
    @Override
    public Ellipsoid createEllipsoid(final String code) throws NoSuchAuthorityCodeException {
        return (Ellipsoid) predefined(code, ELLIPSOID);
    }

    /**
     * Returns a datum for the given EPSG code.
     */
    @Override
    public Datum createDatum(final String code) throws NoSuchAuthorityCodeException {
        return (Datum) predefined(code, DATUM);
    }

    /**
     * Returns a coordinate reference system for the given EPSG code. This method is invoked
     * as a fallback when {@link CRS#forCode(String)} cannot create a CRS for a given code.
     */
    @Override
    public CoordinateReferenceSystem createCoordinateReferenceSystem(final String code) throws NoSuchAuthorityCodeException {
        return (CoordinateReferenceSystem) predefined(code, CRS);
    }

    /**
     * Returns a coordinate system for the given EPSG code. Contrarily to other kinds of objects,
     * coordinate systems are not cached because we cannot use {@link CommonCRS} as a store for
     * them (because all enumerated values use the same coordinate systems). The lack of caching
     * should not be an issue since standalone CS objects (without CRS) are rarely be needed.
     */
    @Override
    public CoordinateSystem createCoordinateSystem(final String code) throws NoSuchAuthorityCodeException {
        return (CoordinateSystem) predefined(code, CS);
    }

    /**
     * Returns a coordinate system axis for the given EPSG code. Axes are not cached for the same
     * reasons than {@link #createCoordinateSystem(String)}.
     */
    @Override
    public CoordinateSystemAxis createCoordinateSystemAxis(final String code) throws NoSuchAuthorityCodeException {
        return (CoordinateSystemAxis) predefined(code, AXIS);
    }

    /**
     * Returns a unit of measurement for the given code.
     */
    @Override
    public Unit<?> createUnit(final String code) throws NoSuchAuthorityCodeException {
        return (Unit) predefined(code, UNIT);
    }

    /**
     * Returns a coordinate reference system, datum or ellipsoid for the given EPSG code.
     */
    @Override
    public IdentifiedObject createObject(final String code) throws NoSuchAuthorityCodeException {
        return (IdentifiedObject) predefined(code, -1 & ~UNIT);
    }

    /**
     * Implementation of all {@code createFoo(String)} methods in this fallback class.
     *
     * @param  code  the EPSG code.
     * @param  kind  any combination of {@code *_MASK} bits.
     * @return the requested object.
     * @throws NoSuchAuthorityCodeException if no matching object has been found.
     */
    private Object predefined(String code, final int kind) throws NoSuchAuthorityCodeException {
        try {
            /*
             * Parse the value after the last ':'. We do not bother to verify if the part before ':' is legal
             * (e.g. "EPSG:4326", "EPSG::4326", "urn:ogc:def:crs:epsg::4326", etc.) because this analysis has
             * already be done by MultiAuthoritiesFactory. We nevertheless skip the prefix in case this factory
             * is used directly (not through MultiAuthoritiesFactory), which should be rare. The main case is
             * when using the factory returned by AuthorityFactories.fallback(…).
             */
            code = CharSequences.trimWhitespaces(code, code.lastIndexOf(Constants.DEFAULT_SEPARATOR) + 1, code.length()).toString();
            final short n = Short.parseShort(code);
            if ((kind & (ELLIPSOID | DATUM | CRS)) != 0) {
                for (final CommonCRS crs : CommonCRS.values()) {
                    /*
                     * In a complete EPSG dataset we could have an ambiguity below because the same code can be used
                     * for datum, ellipsoid and CRS objects. However, in the particular case of this EPSG-subset, we
                     * ensured that there is no such collision - see CommonCRSTest.ensureNoCodeCollision().
                     */
                    if ((kind & ELLIPSOID) != 0  &&  n == crs.ellipsoid) return crs.ellipsoid();
                    if ((kind & DATUM)     != 0  &&  n == crs.datum)     return crs.datum();
                    if ((kind & CRS) != 0) {
                        if (n == crs.geographic) return crs.geographic();
                        if (n == crs.geocentric) return crs.geocentric();
                        if (n == crs.geo3D)      return crs.geographic3D();
                        final double latitude;
                        int zone;
                        if (crs.northUTM != 0 && (zone = n - crs.northUTM) >= crs.firstZone && zone <= crs.lastZone) {
                            latitude = +1;          // Any north latitude below 56°N (because of Norway exception) is okay
                        } else if (crs.southUTM != 0 && (zone = n - crs.southUTM) >= crs.firstZone && zone <= crs.lastZone) {
                            latitude = -1;          // Any south latitude above 80°S (because of UPS south case) is okay.
                        } else if (n == crs.northUPS) {
                            latitude = Latitude.MAX_VALUE;
                            zone     = 30;                  // Any random UTM zone is okay.
                        } else if (n == crs.southUPS) {
                            latitude = Latitude.MIN_VALUE;
                            zone     = 30;                  // Any random UTM zone is okay.
                        } else {
                            continue;
                        }
                        return crs.universal(latitude, TransverseMercator.Zoner.UTM.centralMeridian(zone));
                    }
                }
                if ((kind & (DATUM | CRS)) != 0) {
                    for (final CommonCRS.Vertical candidate : CommonCRS.Vertical.values()) {
                        if (candidate.isEPSG) {
                            if ((kind & DATUM) != 0  &&  candidate.datum == n) return candidate.datum();
                            if ((kind & CRS)   != 0  &&  candidate.crs   == n) return candidate.crs();
                        }
                    }
                }
            }
            /*
             * Other kinds of objects (prime meridian, units of measurement, etc). We check those candidates only after
             * above loop (CRS, datum, etc.) in order to give precedence to CRS if the same code is used for both kinds
             * of objects. We do not bother to cache coordinate system and axis instances.
             */
            if ((kind & PRIME_MERIDIAN) != 0  &&  n == Constants.EPSG_GREENWICH) {
                return CommonCRS.WGS84.primeMeridian();
            }
            if ((kind & CS) != 0) {
                final CoordinateSystem cs = StandardDefinitions.createCoordinateSystem(n, false);
                if (cs != null) return cs;
            }
            if ((kind & AXIS) != 0) {
                final CoordinateSystemAxis axis = StandardDefinitions.createAxis(n, false);
                if (axis != null) return axis;
            }
            if ((kind & UNIT) != 0) {
                final Unit<?> unit = Units.valueOfEPSG(n);
                if (unit != null) return unit;
            }
        } catch (NumberFormatException cause) {
            final NoSuchAuthorityCodeException e = new NoSuchAuthorityCodeException(Resources.format(
                    Resources.Keys.NoSuchAuthorityCode_3, Constants.EPSG, toClass(kind), code), getAuthorityTitle(), code);
            e.initCause(cause);
            throw e;
        }
        throw new NoSuchAuthorityCodeException(Resources.format(Resources.Keys.NoSuchAuthorityCodeInSubset_4,
                Constants.EPSG, toClass(kind), code, getInstallationURL()), getAuthorityTitle(), code);
    }

    /**
     * Returns a URL where users can get more information about the installation process.
     */
    private synchronized String getInstallationURL() {
        if (installationURL == null) {
            installationURL = URLs.EPSG_INSTALL;            // To be used as fallback.
            final ServiceLoader<InstallationResources> services = InstallationResources.load();
            /*
             * Following loop will be executed one or two times. First, we check for resources that are
             * specifically for EPSG geodetic dataset. If none are found, fallback on embedded database.
             */
            boolean embedded = false;
            do {
                final String authority = embedded ? MetadataServices.EMBEDDED : Constants.EPSG;
                for (InstallationResources res : services) {
                    if (res.getAuthorities().contains(authority)) {
                        final String url = res.getInstructionURL();
                        if (url != null) {
                            installationURL = url;
                            return url;
                        }
                    }
                }
            } while ((embedded = !embedded) == true);
        }
        return installationURL;
    }

    /**
     * Returns the interface for the given {@code *_MASK} constant.
     * This is used for formatting error message only.
     */
    private static Class<?> toClass(final int kind) {
        switch (kind) {
            case CRS:            return CoordinateReferenceSystem.class;
            case DATUM:          return Datum.class;
            case ELLIPSOID:      return Ellipsoid.class;
            case PRIME_MERIDIAN: return PrimeMeridian.class;
            case UNIT:           return Unit.class;
            case AXIS:           return CoordinateSystemAxis.class;
            case CS:             return CoordinateSystem.class;
            default:             return IdentifiedObject.class;
        }
    }
}
