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

import java.util.Map;
import java.util.List;
import java.util.Arrays;
import java.util.Collections;
import java.util.StringJoiner;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.io.IOException;
import java.time.Instant;
import javax.measure.Unit;
import org.opengis.util.FactoryException;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.cs.*;
import org.opengis.referencing.datum.*;
import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.crs.CRSFactory;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.GeocentricCRS;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.operation.CoordinateOperationFactory;
import org.opengis.referencing.operation.OperationMethod;
import org.opengis.referencing.operation.Conversion;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.CoordinateSystems;
import org.apache.sis.referencing.crs.AbstractCRS;
import org.apache.sis.referencing.crs.DefaultGeographicCRS;
import org.apache.sis.referencing.crs.DefaultGeocentricCRS;
import org.apache.sis.internal.referencing.provider.Equirectangular;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.internal.util.TemporalUtilities;
import org.apache.sis.storage.DataStoreContentException;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.measure.Units;
import org.apache.sis.math.Vector;


/**
 * Temporary object for building a coordinate reference system from the variables in a netCDF file.
 * This class proceeds by inspecting the coordinate system axes. This is a different approach than
 * {@link GridMapping}, which parses Well Known Text or EPSG codes declared in variable attributes.
 *
 * <p>Different instances are required for the geographic, vertical and temporal components of a CRS,
 * or if a netCDF file uses different CRS for different variables. This builder is used as below:</p>
 *
 * <ol>
 *   <li>Invoke {@link #dispatch(List, Axis)} for all axes in a grid.
 *       Builders for CRS components will added in the given list.</li>
 *   <li>Invoke {@link #build(Decoder)} on each builder prepared in above step.</li>
 *   <li>Assemble the CRS components created in above step in a {@code CompoundCRS}.</li>
 * </ol>
 *
 * The builder type is inferred from axes. The axes are identified by their abbreviations,
 * which is a {@linkplain Axis#abbreviation controlled vocabulary} for this implementation.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.0
 * @since   1.0
 * @module
 */
abstract class CRSBuilder<D extends Datum, CS extends CoordinateSystem> {
    /**
     * The type of datum as a GeoAPI sub-interface of {@link Datum}.
     * Used for verifying the type of cached datum at {@link #datumIndex}.
     */
    private final Class<D> datumType;

    /**
     * Name of the datum on which the CRS is presumed to be based, or {@code ""}. This is used
     * for building a datum name like <cite>"Unknown datum presumably based on GRS 1980"</cite>.
     */
    private final String datumBase;

    /**
     * Index of the cached datum in a {@code Datum[]} array, from 0 inclusive to {@value #DATUM_CACHE_SIZE} exclusive.
     * The datum type at that index must be an instance of {@link #datumType}. We cache only the datum because they do
     * not depend on the netCDF file content in the common case where the CRS is not explicitly specified.
     */
    private final byte datumIndex;

    /**
     * Specify the range of valid number of dimensions, inclusive.
     * The {@link #dimension} value shall be in that range.
     */
    private final byte minDim, maxDim;

    /**
     * Number of valid elements in the {@link #axes} array. The count should not be larger than 3,
     * even if the netCDF file has more axes, because each {@code CRSBuilder} is only for a subset.
     */
    private byte dimension;

    /**
     * The axes to use for creating the coordinate reference system.
     * They are information about netCDF axes, not yet ISO 19111 axes.
     * The axis are listed in "natural" order (reverse of netCDF order).
     * Only the {@link #dimension} first elements are valid.
     */
    private Axis[] axes;

    /**
     * The datum created by {@link #createDatum(DatumFactory, Map)}.
     */
    protected D datum;

    /**
     * The coordinate system created by {@link #createCS(CSFactory, Map, CoordinateSystemAxis[])}.
     */
    protected CS coordinateSystem;

    /**
     * The coordinate reference system that may have been create by {@link #setPredefinedComponents(Decoder)}.
     */
    protected SingleCRS referenceSystem;

    /**
     * Non-fatal exceptions that may occur while building the coordinate reference system.
     * The same exception may be repeated many time, in which case we will report only the
     * first one.
     *
     * @see #recoverableException(NoSuchAuthorityCodeException)
     */
    private NoSuchAuthorityCodeException warnings;

    /**
     * Creates a new CRS builder based on datum of the given type.
     * This constructor is invoked indirectly by {@link #dispatch(List, Axis)}.
     *
     * @param  datumType   the type of datum as a GeoAPI sub-interface of {@link Datum}.
     * @param  datumBase   name of the datum on which the CRS is presumed to be based, or {@code ""}.
     * @param  datumIndex  index of the cached datum in a {@code Datum[]} array.
     * @param  minDim      minimum number of dimensions (usually 1, 2 or 3).
     * @param  maxDim      maximum number of dimensions (usually 1, 2 or 3).
     */
    private CRSBuilder(final Class<D> datumType, final String datumBase, final byte datumIndex, final byte minDim, final byte maxDim) {
        this.datumType  = datumType;
        this.datumBase  = datumBase;
        this.datumIndex = datumIndex;
        this.minDim     = minDim;
        this.maxDim     = maxDim;
        this.axes       = new Axis[3];
    }

    /**
     * Dispatches the given axis to a {@code CRSBuilder} appropriate for the axis type. The axis type is determined
     * from {@link Axis#abbreviation}, taken as a controlled vocabulary. If no suitable {@code CRSBuilder} is found
     * in the given list, then a new one will be created and added to the list.
     *
     * @param  components  the list of builder where to dispatch the axis. May be modified by this method.
     * @param  axis        the axis to add to a builder in the given list.
     * @throws DataStoreContentException if the given axis can not be added in a builder.
     */
    @SuppressWarnings("fallthrough")
    public static void dispatch(final List<CRSBuilder<?,?>> components, final Axis axis) throws DataStoreContentException {
        final Class<? extends CRSBuilder<?,?>> addTo;
        final Supplier<CRSBuilder<?,?>> constructor;
        int alternative = -1;
        switch (axis.abbreviation) {
            case 'h': for (int i=components.size(); --i >= 0;) {        // Can apply to either Geographic or Projected.
                          if (components.get(i) instanceof Projected) {
                              alternative = i;
                              break;
                          }
                      }                    // Fallthrough
            case 'λ': case 'φ':            addTo =  Geographic.class; constructor =  Geographic::new; break;
            case 'θ': case 'Ω': case 'r':  addTo =   Spherical.class; constructor =   Spherical::new; break;
            case 'E': case 'N':            addTo =   Projected.class; constructor =   Projected::new; break;
            case 'H': case 'D':            addTo =    Vertical.class; constructor =    Vertical::new; break;
            case 't':                      addTo =    Temporal.class; constructor =    Temporal::new; break;
            default:                       addTo = Engineering.class; constructor = Engineering::new; break;
        }
        /*
         * If a builder of 'addTo' class already exists, add the axis in the existing builder.
         * We should have at most one builder of each class. But if we nevertheless have more,
         * add to the most recently used builder. If there is no builder, create a new one.
         */
        for (int i=components.size(); --i >= 0;) {
            final CRSBuilder<?,?> builder = components.get(i);
            if (addTo.isInstance(builder) || i == alternative) {
                builder.add(axis);
                return;
            }
        }
        final CRSBuilder<?,?> builder = constructor.get();
        /*
         * Before to add the axis to a newly created builder, verify if we wrongly associated
         * the ellipsoidal height to Geographic builder before. The issue is that ellipsoidal
         * height can be associated to either Geographic or Projected CRS.  If we do not have
         * more information, our first bet is Geographic. If our bet appears to be wrong, the
         * block below fixes it.
         */
        if (addTo == Projected.class) {
previous:   for (int i=components.size(); --i >= 0;) {
                final CRSBuilder<?,?> replace = components.get(i);
                for (final Axis a : replace.axes) {
                    if (a.abbreviation != 'h') {
                        continue previous;                  // Not a lonely ellipsoidal height in a Geographic CRS.
                    }
                }
                for (final Axis a : replace.axes) {         // Should have exactly one element, but we are paranoiac.
                    builder.add(a);
                }
                components.remove(i);
                break;
            }
        }
        builder.add(axis);
        components.add(builder);            // Add only after we ensured that the builder contains at least one axis.
    }

    /**
     * Adds an axis for the coordinate reference system to build. Adding more than 3 axes is usually an error,
     * but this method nevertheless stores those extraneous axis references for building an error message later.
     *
     * @param  axis  the axis to add.
     * @throws DataStoreContentException if the given axis can not be added in this builder.
     */
    private void add(final Axis axis) throws DataStoreContentException {
        if (dimension == Byte.MAX_VALUE) {
            throw new DataStoreContentException(getFirstAxis().coordinates.errors()
                    .getString(Errors.Keys.ExcessiveListSize_2, "axes", (short) (Byte.MAX_VALUE + 1)));
        }
        if (dimension >= axes.length) {
            axes = Arrays.copyOf(axes, dimension * 2);        // Should not happen (see method javadoc).
        }
        axes[dimension++] = axis;
    }

    /**
     * Returns whether the coordinate system has at least 3 axes.
     */
    final boolean is3D() {
        return dimension >= 3;
    }

    /**
     * Returns the first axis. This method is invoked for coordinate reference systems that are known
     * to contain only one axis, for example temporal coordinate systems.
     */
    final Axis getFirstAxis() {
        return axes[0];
    }

    /**
     * Creates the coordinate reference system.
     * This method can be invoked after all axes have been dispatched.
     *
     * @param  decoder  the decoder of the netCDF from which the CRS are constructed.
     */
    public final SingleCRS build(final Decoder decoder) throws FactoryException, DataStoreException, IOException {
        if (dimension < minDim || dimension > maxDim) {
            final Variable axis = getFirstAxis().coordinates;
            throw new DataStoreContentException(axis.resources().getString(Resources.Keys.UnexpectedAxisCount_4,
                    axis.getFilename(), getClass().getSimpleName(), dimension, NamedElement.listNames(axes, dimension, ", ")));
        }
        /*
         * If the subclass can offer coordinate system and datum candidates based on a brief inspection of axes,
         * set the datum, CS and CRS field values to those candidate. Those values do not need to be exact; they
         * will be overwritten later if they do not match the netCDF file content.
         */
        datum = datumType.cast(decoder.datumCache[datumIndex]);         // Should be before 'setPredefinedComponents' call.
        setPredefinedComponents(decoder);
        /*
         * If `setPredefinedComponents(decoder)` offers a datum, we will used it as-is. Otherwise create the datum now.
         * Datum are often not defined in netCDF files, so the above `setPredefinedComponents` method call may have set
         * EPSG::6019 — "Not specified (based on GRS 1980 ellipsoid)". If not, we build a similar name.
         */
        if (datum == null) {
            // Not localized because stored as a String, possibly exported in WKT or GML, and 'datumBase' is in English.
            createDatum(decoder.getDatumFactory(), properties("Unknown datum presumably based upon ".concat(datumBase)));
        }
        decoder.datumCache[datumIndex] = datum;
        /*
         * Verify if a pre-defined coordinate system can be used. This is often the case, for example
         * the EPSG::6424 coordinate system can be used for (longitude, latitude) axes in degrees.
         * Using a pre-defined CS allows us to get more complete definitions (minimum and maximum values, etc.).
         */
        if (coordinateSystem != null) {
            for (int i=dimension; --i >= 0;) {
                final Axis expected = axes[i];
                if (expected == null || !expected.isSameUnitAndDirection(coordinateSystem.getAxis(i))) {
                    coordinateSystem = null;
                    referenceSystem  = null;
                    break;
                }
            }
        }
        /*
         * If 'setPredefinedComponents(decoder)' did not proposed a coordinate system, or if it proposed a CS
         * but its axes do not match the axes in the netCDF file, then create a new coordinate system here.
         */
        if (referenceSystem == null) {
            final Map<String,?> properties;
            if (coordinateSystem == null) {
                // Fallback if the coordinate system is not predefined.
                final StringJoiner joiner = new StringJoiner(" ");
                final CSFactory csFactory = decoder.getCSFactory();
                final CoordinateSystemAxis[] iso = new CoordinateSystemAxis[dimension];
                for (int i=0; i<iso.length; i++) {
                    final Axis axis = axes[i];
                    joiner.add(axis.getName());
                    iso[i] = axis.toISO(csFactory, i);
                }
                createCS(csFactory, properties(joiner.toString()), iso);
                properties = properties(coordinateSystem.getName());
            } else {
                properties = properties(NamedElement.listNames(axes, dimension, " "));
            }
            createCRS(decoder.getCRSFactory(), properties);
        }
        /*
         * Creates the coordinate reference system using current value of 'datum' and 'coordinateSystem' fields.
         * The coordinate system initially have a [-180 … +180]° longitude range. If the actual coordinate values
         * are outside that range, switch the longitude range to [0 … 360]°.
         */
        final CoordinateSystem cs = referenceSystem.getCoordinateSystem();
        for (int i=cs.getDimension(); --i >= 0;) {
            final CoordinateSystemAxis axis = cs.getAxis(i);
            if (RangeMeaning.WRAPAROUND.equals(axis.getRangeMeaning())) {
                final Vector coordinates = axes[i].read();                          // Typically a cached vector.
                final int length = coordinates.size();
                if (length != 0) {
                    final double first = coordinates.doubleValue(0);
                    final double last  = coordinates.doubleValue(length - 1);
                    if (Math.min(first, last) >= 0 && Math.max(first, last) > axis.getMaximumValue()) {
                        referenceSystem = (SingleCRS) AbstractCRS.castOrCopy(referenceSystem).forConvention(AxesConvention.POSITIVE_RANGE);
                        break;
                    }
                }
            }
        }
        if (warnings != null) {
            decoder.listeners.warning(Level.FINE, null, warnings);
        }
        return referenceSystem;
    }

    /**
     * Reports a non-fatal exception that may occur during {@link #setPredefinedComponents(Decoder)}.
     * In order to avoid repeating the same warning many times, this method collects the warnings
     * together and reports them in a single log record after we finished creating the CRS.
     */
    final void recoverableException(final NoSuchAuthorityCodeException e) {
        if (warnings == null) warnings = e;
        else warnings.addSuppressed(e);
    }

    /**
     * Returns the properties to give to factory {@code create} methods.
     *
     * @param  name  name of the geodetic object (datum, coordinate system, …) to create.
     */
    private static Map<String,?> properties(final Object name) {
        return Collections.singletonMap(IdentifiedObject.NAME_KEY, name);
    }

    /**
     * Returns the EPSG code of a possible coordinate system from EPSG database. This method proceed by brief
     * inspection of axis directions and units; there is no guarantees that the coordinate system returned by
     * this method match the axes defined in the netCDF file. It is caller's responsibility to verify.
     * This is a helper method for {@link #setPredefinedComponents(Decoder)} implementations.
     *
     * @param  defaultUnit  the unit to use if unit definition is missing in the netCDF file.
     * @return EPSG code of a CS candidate, or {@code null} if none.
     *
     * @see Geodetic#isPredefinedCS(Unit)
     */
    final Integer epsgCandidateCS(final Unit<?> defaultUnit) {
        Unit<?> unit = getFirstAxis().getUnit();
        if (unit == null) unit = defaultUnit;
        final AxisDirection[] directions = new AxisDirection[dimension];
        for (int i=0; i<directions.length; i++) {
            directions[i] = axes[i].direction;
        }
        return CoordinateSystems.getEpsgCode(unit, directions);
    }

    /**
     * If a brief inspection of unit and direction of the {@linkplain #getFirstAxis() first axis} suggests
     * that a predefined coordinate system could be used, sets the {@link #coordinateSystem} field to that CS.
     * The coordinate system does not need to be a full match since all axes will be verified by the caller.
     * This method is invoked before to fallback on {@link #createCS(CSFactory, Map, CoordinateSystemAxis[])}.
     *
     * <p>This method may opportunistically set the {@link #datum} and {@link #referenceSystem} fields if it
     * can propose a CRS candidate instead than only a CS candidate.</p>
     */
    abstract void setPredefinedComponents(Decoder decoder) throws FactoryException;

    /**
     * Creates the datum for the coordinate reference system to build. The datum are generally not specified in netCDF files.
     * To make that clearer, this method builds datum with names like <cite>"Unknown datum presumably based on GRS 1980"</cite>.
     * The newly created datum is assigned to the {@link #datum} field.
     *
     * @param  factory     the factory to use for creating the datum.
     * @param  properties  contains the name of the datum to create.
     */
    abstract void createDatum(DatumFactory factory, Map<String,?> properties) throws FactoryException;

    /**
     * Creates the coordinate system from the given axes. This method is invoked only after we
     * verified that the number of axes is inside the {@link #minDim} … {@link #maxDim} range.
     * The newly created coordinate system is assigned to the {@link #coordinateSystem} field.
     *
     * @param  factory     the factory to use for creating the coordinate system.
     * @param  properties  contains the name of the coordinate system to create.
     * @param  axes        the axes of the coordinate system.
     */
    abstract void createCS(CSFactory factory, Map<String,?> properties, CoordinateSystemAxis[] axes) throws FactoryException;

    /**
     * Creates the coordinate reference system from the values in {@link #datum} and {@link #coordinateSystem} fields.
     * This method is invoked only if {@link #referenceSystem} is still {@code null} or its axes do not correspond to
     * the expected axis. The newly created reference system is assigned to the {@link #referenceSystem} field.
     *
     * @param  factory     the factory to use for creating the coordinate reference system.
     * @param  properties  contains the name of the coordinate reference system to create.
     */
    abstract void createCRS(CRSFactory factory, Map<String,?> properties) throws FactoryException;




    /**
     * Base classes of {@link Spherical}, {@link Geographic} and {@link Projected} builders.
     * They all have in common to be based on a {@link GeodeticDatum}.
     */
    private abstract static class Geodetic<CS extends CoordinateSystem> extends CRSBuilder<GeodeticDatum, CS> {
        /**
         * The coordinate reference system which is presumed the basis of datum on netCDF files.
         */
        protected CommonCRS defaultCRS;

        /**
         * Whether the coordinate system has longitude before latitude.
         * This flag is set as a side-effect of {@link #isPredefinedCS(Unit)} method call.
         */
        protected boolean isLongitudeFirst;

        /**
         * For subclasses constructors.
         *
         * @param  minDim  minimum number of dimensions (2 or 3).
         */
        Geodetic(final byte minDim) {
            super(GeodeticDatum.class, "GRS 1980", (byte) 0, minDim, (byte) 3);
        }

        /**
         * Initializes this builder before {@link #build(Decoder)} execution.
         */
        @Override void setPredefinedComponents(final Decoder decoder) throws FactoryException {
            defaultCRS = decoder.convention().defaultHorizontalCRS(false);
        }

        /**
         * Creates a {@link GeodeticDatum} for <cite>"Unknown datum presumably based on GRS 1980"</cite>.
         * This method is invoked only if {@link #setPredefinedComponents(Decoder)} failed to create a datum.
         */
        @Override final void createDatum(DatumFactory factory, Map<String,?> properties) throws FactoryException {
            final GeodeticDatum template = defaultCRS.datum();
            datum = factory.createGeodeticDatum(properties, template.getEllipsoid(), template.getPrimeMeridian());
        }

        /**
         * Returns {@code true} if the coordinate system may be one of the predefined CS. A returns value of {@code true}
         * is not a guarantee that the coordinate system in the netCDF file matches the predefined CS; it only tells that
         * this is reasonable chances to be the case based on a brief inspection of the first coordinate system axis.
         * If {@code true}, then {@link #isLongitudeFirst} will have been set to an indication of axis order.
         *
         * @param  expected  the expected unit of measurement of the first axis.
         *
         * @see #epsgCandidateCS(Unit)
         */
        final boolean isPredefinedCS(final Unit<?> expected) {
            final Axis axis = getFirstAxis();
            final Unit<?> unit = axis.getUnit();
            if (unit == null || expected.equals(unit)) {
                isLongitudeFirst = AxisDirection.EAST.equals(axis.direction);
                if (isLongitudeFirst || AxisDirection.NORTH.equals(axis.direction)) {
                    return true;
                }
            }
            return false;
        }
    }




    /**
     * Builder for geocentric CRS with (θ,Ω,r) axes.
     */
    private static final class Spherical extends Geodetic<SphericalCS> {
        /**
         * Creates a new builder (invoked by lambda function).
         */
        public Spherical() {
            super((byte) 3);
        }

        /**
         * Possibly sets {@link #datum} and {@link #coordinateSystem} to predefined objects
         * matching the axes defined in the netCDF file.
         */
        @Override void setPredefinedComponents(final Decoder decoder) throws FactoryException {
            super.setPredefinedComponents(decoder);
            if (isPredefinedCS(Units.DEGREE)) {
                GeocentricCRS crs = defaultCRS.spherical();
                if (isLongitudeFirst) {
                    crs = DefaultGeocentricCRS.castOrCopy(crs).forConvention(AxesConvention.RIGHT_HANDED);
                }
                referenceSystem  = crs;
                coordinateSystem = (SphericalCS) crs.getCoordinateSystem();
                datum            = crs.getDatum();
            } else {
                datum = defaultCRS.datum();
            }
        }

        /**
         * Creates the three-dimensional {@link SphericalCS} from given axes. This method is invoked only
         * if {@link #setPredefinedComponents(Decoder)} failed to assign a CS or if {@link #build(Decoder)}
         * found that the {@link #coordinateSystem} does not have compatible axes.
         */
        @Override void createCS(CSFactory factory, Map<String,?> properties, CoordinateSystemAxis[] axes) throws FactoryException {
            coordinateSystem = factory.createSphericalCS(properties, axes[0], axes[1], axes[2]);
        }

        /**
         * Creates the coordinate reference system from datum and coordinate system computed in previous steps.
         * This method is invoked under conditions similar to the ones of above {@code createCS(…)} method.
         */
        @Override void createCRS(CRSFactory factory, Map<String,?> properties) throws FactoryException {
            referenceSystem = factory.createGeocentricCRS(properties, datum, coordinateSystem);
        }
    }




    /**
     * Geographic CRS with (λ,φ,h) axes.
     * The height, if present, is ellipsoidal height.
     */
    private static final class Geographic extends Geodetic<EllipsoidalCS> {
        /**
         * Creates a new builder (invoked by lambda function).
         */
        public Geographic() {
            super((byte) 2);
        }

        /**
         * Possibly sets {@link #datum}, {@link #coordinateSystem} and {@link #referenceSystem}
         * to predefined objects matching the axes defined in the netCDF file.
         */
        @Override void setPredefinedComponents(final Decoder decoder) throws FactoryException {
            super.setPredefinedComponents(decoder);
            if (isPredefinedCS(Units.DEGREE)) {
                GeographicCRS crs;
                if (is3D()) {
                    crs = defaultCRS.geographic3D();
                    if (isLongitudeFirst) {
                        crs = DefaultGeographicCRS.castOrCopy(crs).forConvention(AxesConvention.RIGHT_HANDED);
                    }
                } else if (isLongitudeFirst) {
                    crs = defaultCRS.normalizedGeographic();
                } else {
                    crs = defaultCRS.geographic();
                }
                referenceSystem  = crs;
                coordinateSystem = crs.getCoordinateSystem();
                datum            = crs.getDatum();
            } else {
                datum = defaultCRS.datum();
                final Integer epsg = epsgCandidateCS(Units.DEGREE);
                if (epsg != null) try {
                    coordinateSystem = decoder.getCSAuthorityFactory().createEllipsoidalCS(epsg.toString());
                } catch (NoSuchAuthorityCodeException e) {
                    recoverableException(e);
                }
            }
        }

        /**
         * Creates the two- or three-dimensional {@link EllipsoidalCS} from given axes. This method is invoked only if
         * {@link #setPredefinedComponents(Decoder)} failed to assign a coordinate system or if {@link #build(Decoder)}
         * found that the {@link #coordinateSystem} does not have compatible axes.
         */
        @Override void createCS(CSFactory factory, Map<String,?> properties, CoordinateSystemAxis[] axes) throws FactoryException {
            if (axes.length > 2) {
                coordinateSystem = factory.createEllipsoidalCS(properties, axes[0], axes[1], axes[2]);
            } else {
                coordinateSystem = factory.createEllipsoidalCS(properties, axes[0], axes[1]);
            }
        }

        /**
         * Creates the coordinate reference system from datum and coordinate system computed in previous steps.
         * This method is invoked under conditions similar to the ones of above {@code createCS(…)} method.
         */
        @Override void createCRS(CRSFactory factory, Map<String,?> properties) throws FactoryException {
            referenceSystem = factory.createGeographicCRS(properties, datum, coordinateSystem);
        }
    }




    /**
     * Projected CRS with (E,N,h) axes. There is not enough information in a netCDF files for creating the right
     * map projection, unless {@code "grid_mapping"} attributes are specified. If insufficient information, this
     * class creates an unknown map projection based on Plate Carrée. Note that this map projection may be replaced
     * by {@link GridMapping#crs} at a later stage.
     */
    private static final class Projected extends Geodetic<CartesianCS> {
        /**
         * The spherical variant of {@link #defaultCRS}.
         */
        private CommonCRS sphericalDatum;

        /**
         * Defining conversion for "Not specified (presumed Plate Carrée)". This conversion use spherical formulas.
         * Consequently it should be used with {@link #sphericalDatum} instead of {@link #defaultCRS}.
         */
        private static final Conversion UNKNOWN_PROJECTION;
        static {
            final CoordinateOperationFactory factory = DefaultFactories.forBuildin(CoordinateOperationFactory.class);
            try {
                final OperationMethod method = factory.getOperationMethod(Equirectangular.NAME);
                UNKNOWN_PROJECTION = factory.createDefiningConversion(
                        properties("Not specified (presumed Plate Carrée)"),
                        method, method.getParameters().createValue());
            } catch (FactoryException e) {
                throw new ExceptionInInitializerError(e);
            }
        }

        /**
         * Creates a new builder (invoked by lambda function).
         */
        public Projected() {
            super((byte) 2);
        }

        /**
         * Possibly sets {@link #datum}, {@link #coordinateSystem} and {@link #referenceSystem}
         * to predefined objects matching the axes defined in the netCDF file.
         */
        @Override void setPredefinedComponents(final Decoder decoder) throws FactoryException {
            super.setPredefinedComponents(decoder);
            sphericalDatum = decoder.convention().defaultHorizontalCRS(true);
            datum = sphericalDatum.datum();
            if (isPredefinedCS(Units.METRE)) {
                coordinateSystem = decoder.getStandardProjectedCS();
            }
        }

        /**
         * Creates the two- or three-dimensional {@link CartesianCS} from given axes. This method is invoked only if
         * {@link #setPredefinedComponents(Decoder)} failed to assign a coordinate system or if {@link #build(Decoder)}
         * found that the {@link #coordinateSystem} does not have compatible axes.
         */
        @Override void createCS(CSFactory factory, Map<String,?> properties, CoordinateSystemAxis[] axes) throws FactoryException {
            if (axes.length > 2) {
                coordinateSystem = factory.createCartesianCS(properties, axes[0], axes[1], axes[2]);
            } else {
                coordinateSystem = factory.createCartesianCS(properties, axes[0], axes[1]);
            }
        }

        /**
         * Creates the coordinate reference system from datum and coordinate system computed in previous steps.
         * The datum for this method is based on a sphere.
         */
        @Override void createCRS(CRSFactory factory, Map<String,?> properties) throws FactoryException {
            final boolean is3D = (coordinateSystem.getDimension() >= 3);
            GeographicCRS baseCRS = is3D ? sphericalDatum.geographic3D() : sphericalDatum.geographic();
            if (!baseCRS.getDatum().equals(datum)) {
                baseCRS = factory.createGeographicCRS(properties, datum, baseCRS.getCoordinateSystem());
            }
            referenceSystem = factory.createProjectedCRS(properties, baseCRS, UNKNOWN_PROJECTION, coordinateSystem);
        }
    }




    /**
     * Vertical CRS with (H) or (D) axis.
     * Used for mean sea level (not for ellipsoidal height).
     */
    private static final class Vertical extends CRSBuilder<VerticalDatum, VerticalCS> {
        /**
         * Creates a new builder (invoked by lambda function).
         */
        public Vertical() {
            super(VerticalDatum.class, "Mean Sea Level", (byte) 1, (byte) 1, (byte) 1);
        }

        /**
         * Possibly sets {@link #coordinateSystem} to a predefined CS matching the axes defined in the netCDF file.
         */
        @Override void setPredefinedComponents(final Decoder decoder) {
            final Axis axis = getFirstAxis();
            final Unit<?> unit = axis.getUnit();
            final CommonCRS.Vertical predefined;
            if (Units.METRE.equals(unit)) {
                if (AxisDirection.UP.equals(axis.direction)) {
                    predefined = CommonCRS.Vertical.MEAN_SEA_LEVEL;
                } else {
                    predefined = CommonCRS.Vertical.DEPTH;
                }
            } else if (Units.HECTOPASCAL.equals(unit)) {
                predefined = CommonCRS.Vertical.BAROMETRIC;
            } else {
                return;
            }
            coordinateSystem = predefined.crs().getCoordinateSystem();
        }

        /**
         * Creates a {@link VerticalDatum} for <cite>"Unknown datum based on Mean Sea Level"</cite>.
         */
        @Override void createDatum(DatumFactory factory, Map<String,?> properties) throws FactoryException {
            datum = factory.createVerticalDatum(properties, VerticalDatumType.GEOIDAL);
        }

        /**
         * Creates the one-dimensional {@link VerticalCS} from given axes. This method is invoked
         * only if {@link #setPredefinedComponents(Decoder)} failed to assign a coordinate system
         * or if {@link #build(Decoder)} found that the axis or direction are not compatible.
         */
        @Override void createCS(CSFactory factory, Map<String,?> properties, CoordinateSystemAxis[] axes) throws FactoryException {
            coordinateSystem = factory.createVerticalCS(properties, axes[0]);
        }

        /**
         * Creates the coordinate reference system from datum and coordinate system computed in previous steps.
         */
        @Override void createCRS(CRSFactory factory, Map<String,?> properties) throws FactoryException {
            referenceSystem =  factory.createVerticalCRS(properties, datum, coordinateSystem);
        }
    }




    /**
     * Temporal CRS with (t) axis. Its datum need to be built
     * in a special way since it contains the time origin.
     */
    private static final class Temporal extends CRSBuilder<TemporalDatum, TimeCS> {
        /**
         * Creates a new builder (invoked by lambda function).
         */
        public Temporal() {
            super(TemporalDatum.class, "", (byte) 2, (byte) 1, (byte) 1);
        }

        /**
         * Possibly sets {@link #coordinateSystem} to a predefined CS matching the axes defined in the netCDF file.
         */
        @Override void setPredefinedComponents(final Decoder decoder) {
            final Axis axis = getFirstAxis();
            final Unit<?> unit = axis.getUnit();
            final CommonCRS.Temporal predefined;
            if (Units.DAY.equals(unit)) {
                predefined = CommonCRS.Temporal.JULIAN;
            } else if (Units.SECOND.equals(unit)) {
                predefined = CommonCRS.Temporal.UNIX;
            } else if (Units.MILLISECOND.equals(unit)) {
                predefined = CommonCRS.Temporal.JAVA;
            } else {
                return;
            }
            coordinateSystem = predefined.crs().getCoordinateSystem();
        }

        /**
         * Creates a {@link TemporalDatum} for <cite>"Unknown datum based on …"</cite>.
         */
        @Override void createDatum(DatumFactory factory, Map<String,?> properties) throws FactoryException {
            final Axis axis = getFirstAxis();
            axis.getUnit();                                     // Force epoch parsing if not already done.
            Instant epoch = axis.coordinates.epoch;
            final CommonCRS.Temporal c = CommonCRS.Temporal.forEpoch(epoch);
            if (c != null) {
                datum = c.datum();
            } else {
                properties = properties("Time since " + epoch);
                datum = factory.createTemporalDatum(properties, TemporalUtilities.toDate(epoch));
            }
        }

        /**
         * Creates the one-dimensional {@link TimeCS} from given axes. This method is invoked only
         * if {@link #setPredefinedComponents(Decoder)} failed to assign a coordinate system or if
         * {@link #build(Decoder)} found that the axis or direction are not compatible.
         */
        @Override void createCS(CSFactory factory, Map<String,?> properties, CoordinateSystemAxis[] axes) throws FactoryException {
            coordinateSystem = factory.createTimeCS(properties, axes[0]);
        }

        /**
         * Creates the coordinate reference system from datum and coordinate system computed in previous steps.
         */
        @Override void createCRS(CRSFactory factory, Map<String,?> properties) throws FactoryException {
            properties = properties(getFirstAxis().coordinates.getUnitsString());
            referenceSystem =  factory.createTemporalCRS(properties, datum, coordinateSystem);
        }
    }




    /**
     * Unknown CRS with (x,y,z) axes.
     */
    private static final class Engineering extends CRSBuilder<EngineeringDatum, AffineCS> {
        /**
         * Creates a new builder (invoked by lambda function).
         */
        public Engineering() {
            super(EngineeringDatum.class, "affine coordinate system", (byte) 3, (byte) 2, (byte) 3);
        }

        /**
         * No-op since we have no predefined engineering CRS.
         */
        @Override void setPredefinedComponents(final Decoder decoder) {
        }

        /**
         * Creates a {@link VerticalDatum} for <cite>"Unknown datum based on affine coordinate system"</cite>.
         */
        @Override void createDatum(DatumFactory factory, Map<String,?> properties) throws FactoryException {
            datum = factory.createEngineeringDatum(properties);
        }

        /**
         * Creates two- or three-dimensional {@link AffineCS} from given axes.
         */
        @Override void createCS(CSFactory factory, Map<String,?> properties, CoordinateSystemAxis[] axes) throws FactoryException {
            if (axes.length > 2) {
                coordinateSystem = factory.createAffineCS(properties, axes[0], axes[1], axes[2]);
            } else {
                coordinateSystem = factory.createAffineCS(properties, axes[0], axes[1]);
            }
        }

        /**
         * Creates the coordinate reference system from datum and coordinate system computed in previous steps.
         */
        @Override void createCRS(CRSFactory factory, Map<String,?> properties) throws FactoryException {
            referenceSystem =  factory.createEngineeringCRS(properties, datum, coordinateSystem);
        }
    }

    /**
     * Maximal {@link #datumIndex} value +1. The maximal value can be seen in the call to {@code super(…)} constructor
     * in the last inner class defined above.
     */
    static final int DATUM_CACHE_SIZE = 4;
}
