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

import java.lang.reflect.Array;
import java.util.function.Function;
import javax.measure.Unit;
import javax.measure.Quantity;
import javax.measure.quantity.Angle;
import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.GeneralParameterDescriptor;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.ReferenceIdentifier;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.datum.PrimeMeridian;
import org.opengis.referencing.datum.Ellipsoid;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.crs.AbstractCRS;
import org.apache.sis.referencing.cs.AbstractCS;
import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
import org.apache.sis.referencing.datum.AbstractDatum;
import org.apache.sis.referencing.datum.DefaultGeodeticDatum;
import org.apache.sis.referencing.datum.DefaultPrimeMeridian;
import org.apache.sis.referencing.datum.DefaultEllipsoid;
import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.internal.referencing.provider.Affine;
import org.apache.sis.parameter.DefaultParameterValue;
import org.apache.sis.parameter.Parameterized;
import org.apache.sis.io.wkt.ElementKind;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.measure.Units;
import org.apache.sis.util.Static;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.internal.util.Numerics;
import org.apache.sis.math.DecimalFunctions;
import org.apache.sis.math.Vector;


/**
 * Utility methods for referencing WKT formatting.
 *
 * This class provides a set of {@code toFormattable(…)} for various {@link IdentifiedObject} subtypes.
 * It is important to <strong>not</strong> provide a generic {@code toFormattable(IdentifiedObject)}
 * method, because the user may choose to implement more than one GeoAPI interface for the same object.
 * We need to be specific in order to select the right "aspect" of the given object.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.0
 * @since   0.4
 * @module
 */
public final class WKTUtilities extends Static {
    /**
     * Do not allow instantiation of this class.
     */
    private WKTUtilities() {
    }

    /**
     * Returns the WKT type of the given interface.
     *
     * For {@link CoordinateSystem} base type, the returned value shall be one of
     * {@code affine}, {@code Cartesian}, {@code cylindrical}, {@code ellipsoidal}, {@code linear},
     * {@code parametric}, {@code polar}, {@code spherical}, {@code temporal} or {@code vertical}.
     *
     * @param  base  the abstract base interface.
     * @param  type  the interface or classes for which to get the WKT type.
     * @return the WKT type for the given class or interface, or {@code null} if none.
     *
     * @see ReferencingUtilities#toPropertyName(Class, Class)
     */
    public static String toType(final Class<?> base, final Class<?> type) {
        if (type != base) {
            final StringBuilder name = ReferencingUtilities.toPropertyName(base, type);
            if (name != null) {
                int end = name.length() - 2;
                if (CharSequences.regionMatches(name, end, "CS")) {
                    name.setLength(end);
                    if ("time".contentEquals(name)) {
                        return "temporal";
                    }
                    if (CharSequences.regionMatches(name, 0, "cartesian")) {
                        name.setCharAt(0, 'C');     // "Cartesian"
                    }
                    return name.toString();
                }
            }
        }
        return null;
    }

    /**
     * Returns the given coordinate reference system as a formattable object.
     *
     * @param  object  the coordinate reference system, or {@code null}.
     * @return the given coordinate reference system as a formattable object, or {@code null}.
     */
    public static FormattableObject toFormattable(final CoordinateReferenceSystem object) {
        if (object instanceof FormattableObject) {
            return (FormattableObject) object;
        } else {
            return AbstractCRS.castOrCopy(object);
        }
    }

    /**
     * Returns the given coordinate system as a formattable object.
     *
     * @param  object  the coordinate system, or {@code null}.
     * @return the given coordinate system as a formattable object, or {@code null}.
     */
    public static FormattableObject toFormattable(final CoordinateSystem object) {
        if (object instanceof FormattableObject) {
            return (FormattableObject) object;
        } else {
            return AbstractCS.castOrCopy(object);
        }
    }

    /**
     * Returns the given coordinate system axis as a formattable object.
     *
     * @param  object  the coordinate system axis, or {@code null}.
     * @return the given coordinate system axis as a formattable object, or {@code null}.
     */
    public static FormattableObject toFormattable(final CoordinateSystemAxis object) {
        if (object instanceof FormattableObject) {
            return (FormattableObject) object;
        } else {
            return DefaultCoordinateSystemAxis.castOrCopy(object);
        }
    }

    /**
     * Returns the given datum as a formattable object.
     *
     * @param  object  the datum, or {@code null}.
     * @return the given datum as a formattable object, or {@code null}.
     */
    public static FormattableObject toFormattable(final Datum object) {
        if (object instanceof FormattableObject) {
            return (FormattableObject) object;
        } else {
            return AbstractDatum.castOrCopy(object);
        }
    }

    /**
     * Returns the given geodetic datum as a formattable object.
     *
     * @param  object  the datum, or {@code null}.
     * @return the given datum as a formattable object, or {@code null}.
     */
    public static FormattableObject toFormattable(final GeodeticDatum object) {
        if (object instanceof FormattableObject) {
            return (FormattableObject) object;
        } else {
            return DefaultGeodeticDatum.castOrCopy(object);
        }
    }

    /**
     * Returns the ellipsoid as a formattable object.
     *
     * @param  object  the ellipsoid, or {@code null}.
     * @return the given ellipsoid as a formattable object, or {@code null}.
     */
    public static FormattableObject toFormattable(final Ellipsoid object) {
        if (object instanceof FormattableObject) {
            return (FormattableObject) object;
        } else {
            return DefaultEllipsoid.castOrCopy(object);
        }
    }

    /**
     * Returns the given prime meridian as a formattable object.
     *
     * @param  object  the prime meridian, or {@code null}.
     * @return the given prime meridian as a formattable object, or {@code null}.
     */
    public static FormattableObject toFormattable(final PrimeMeridian object) {
        if (object instanceof FormattableObject) {
            return (FormattableObject) object;
        } else {
            return DefaultPrimeMeridian.castOrCopy(object);
        }
    }

    /**
     * Converts the given object in a {@code FormattableObject} instance. Callers should verify that the
     * given object is not already an instance of {@code FormattableObject} before to invoke this method.
     * This method returns {@code null} if it can not convert the object.
     *
     * @param  object    the object to wrap.
     * @param  internal  {@code true} if the formatting convention is {@code Convention.INTERNAL}.
     * @return the given object converted to a {@code FormattableObject} instance, or {@code null}.
     */
    public static FormattableObject toFormattable(final MathTransform object, boolean internal) {
        Matrix matrix;
        final ParameterValueGroup parameters;
        if (internal && (matrix = MathTransforms.getMatrix(object)) != null) {
            parameters = Affine.parameters(matrix);
        } else if (object instanceof Parameterized) {
            parameters = ((Parameterized) object).getParameterValues();
        } else {
            matrix = MathTransforms.getMatrix(object);
            if (matrix == null) {
                return null;
            }
            parameters = Affine.parameters(matrix);
        }
        return new FormattableObject() {
            @Override protected String formatTo(final Formatter formatter) {
                WKTUtilities.appendParamMT(parameters, formatter);
                return WKTKeywords.Param_MT;
            }
        };
    }

    /**
     * If the given unit is one of the unit that can not be formatted without ambiguity in WKT format,
     * return a proposed replacement. Otherwise returns {@code unit} unchanged.
     *
     * @param  <Q>   the unit dimension.
     * @param  unit  the unit to test.
     * @return the replacement to format, or {@code unit} if not needed.
     *
     * @since 0.8
     */
    @SuppressWarnings("unchecked")
    public static <Q extends Quantity<Q>> Unit<Q> toFormattable(Unit<Q> unit) {
        if (Units.isAngular(unit)) {
            if (!((Unit<Angle>) unit).getConverterTo(Units.RADIAN).isLinear()) {
                unit = (Unit<Q>) Units.DEGREE;
            }
        }
        return unit;
    }

    /**
     * Appends the name of the given object to the formatter.
     *
     * @param  object     the object from which to get the name.
     * @param  formatter  the formatter where to append the name.
     * @param  type       the key of colors to apply if syntax colors are enabled.
     */
    public static void appendName(final IdentifiedObject object, final Formatter formatter, final ElementKind type) {
        String name = IdentifiedObjects.getName(object, formatter.getNameAuthority());
        if (name == null) {
            name = IdentifiedObjects.getName(object, null);
            if (name == null) {
                name = Vocabulary.getResources(formatter.getLocale()).getString(Vocabulary.Keys.Unnamed);
            }
        }
        formatter.append(name, (type != null) ? type : ElementKind.NAME);
    }

    /**
     * Appends a {@linkplain ParameterValueGroup group of parameters} in a {@code Param_MT[…]} element.
     *
     * @param  parameters  the parameter to append to the WKT, or {@code null} if none.
     * @param  formatter   the formatter where to append the parameter.
     */
    public static void appendParamMT(final ParameterValueGroup parameters, final Formatter formatter) {
        if (parameters != null) {
            appendName(parameters.getDescriptor(), formatter, ElementKind.PARAMETER);
            append(parameters, formatter);
        }
    }

    /**
     * Appends a {@linkplain ParameterValue parameter} in a {@code PARAMETER[…]} element.
     * If the supplied parameter is actually a {@linkplain ParameterValueGroup parameter group},
     * all contained parameters will be flattened in a single list.
     *
     * @param  parameter  the parameter to append to the WKT, or {@code null} if none.
     * @param  formatter  the formatter where to append the parameter.
     */
    public static void append(GeneralParameterValue parameter, final Formatter formatter) {
        if (parameter instanceof ParameterValueGroup) {
            boolean first = true;
            for (final GeneralParameterValue param : ((ParameterValueGroup) parameter).values()) {
                if (first) {
                    formatter.newLine();
                    first = false;
                }
                append(param, formatter);
            }
        }
        if (parameter instanceof ParameterValue<?>) {
            if (!(parameter instanceof FormattableObject)) {
                parameter = new DefaultParameterValue<>((ParameterValue<?>) parameter);
            }
            formatter.append((FormattableObject) parameter);
            formatter.newLine();
        }
    }

    /**
     * Returns {@code true} if the given parameter is defined in the EPSG code space. We handle EPSG
     * parameters in a special way because Apache SIS uses the EPSG geodetic dataset as the primary
     * source of coordinate operation definitions.
     *
     * <p>We intentionally don't define {@code isEPSG(OperationMethod)} method because the operation
     * method may be the inverse of an EPSG method (for example "Inverse of Mercator (variant A)")
     * which would not be recognized. Instead, {@code isEPSG(method.getParameters())} should work.</p>
     *
     * @param  descriptor   the parameter or group of parameters to inspect.
     * @param  ifUndefined  the value to return if the code space is undefined.
     * @return whether the given parameter is an EPSG parameter.
     */
    public static boolean isEPSG(final GeneralParameterDescriptor descriptor, final boolean ifUndefined) {
        if (descriptor != null) {
            final ReferenceIdentifier id = descriptor.getName();
            if (id != null) {
                final String cs = id.getCodeSpace();
                if (cs != null) {
                    return Constants.EPSG.equalsIgnoreCase(cs);
                }
            }
        }
        return ifUndefined;
    }

    /**
     * Suggests an amount of fraction digits to use for formatting numbers in each column of the given sequence
     * of points. The number of fraction digits may be negative if we could round the numbers to 10, <i>etc</i>.
     *
     * @param  crs     the coordinate reference system for each points, or {@code null} if unknown.
     * @param  points  the sequence of points. It is not required that each point has the same dimension.
     * @return suggested amount of fraction digits as an array as long as the longest row.
     */
    public static int[] suggestFractionDigits(final CoordinateReferenceSystem crs, final Vector[] points) {
        final int[] fractionDigits = Numerics.suggestFractionDigits(points);
        final Ellipsoid ellipsoid = ReferencingUtilities.getEllipsoid(crs);
        if (ellipsoid != null) {
            /*
             * Use heuristic precisions for geodetic or projected CRS. We do not apply those heuristics
             * for other kind of CRS (e.g. engineering) because we do not know what could be the size
             * of the object attached to the CRS.
             */
            final CoordinateSystem cs = crs.getCoordinateSystem();
            final int dimension = Math.min(cs.getDimension(), fractionDigits.length);
            final double scale = Formulas.scaleComparedToEarth(ellipsoid);
            for (int i=0; i<dimension; i++) {
                final Unit<?> unit = cs.getAxis(i).getUnit();
                double precision;
                if (Units.isLinear(unit)) {
                    precision = Formulas.LINEAR_TOLERANCE * scale;                          // In metres
                } else if (Units.isAngular(unit)) {
                    precision = Formulas.ANGULAR_TOLERANCE * (Math.PI / 180) * scale;       // In radians
                } else if (Units.isTemporal(unit)) {
                    precision = Formulas.TEMPORAL_TOLERANCE;                                // In seconds
                } else {
                    continue;
                }
                precision /= Units.toStandardUnit(unit);                // In units used by the coordinates.
                final int f = DecimalFunctions.fractionDigitsForDelta(precision, false);
                if (f > fractionDigits[i]) {
                    fractionDigits[i] = f;                              // Use at least the heuristic precision.
                }
            }
        }
        return fractionDigits;
    }

    /**
     * Returns the values in the corners and in the center of the given tensor. The values are returned in a
     * <var>n</var>-dimensional array of {@link Number} where <var>n</var> is the length of {@code size}.
     * If some values have been skipped, {@code null} values are inserted in the rows or columns where the
     * skipping occurs.
     *
     * @param  tensor      function providing values of the tensor. Inputs are indices of the desired value with
     *                     index in each dimension ranging from 0 inclusive to {@code size[dimension]} exclusive.
     * @param  size        size of the tensor. The length of this array is the tensor dimension.
     * @param  cornerSize  number of values to keep in each corner.
     * @return <var>n</var>-dimensional array of {@link Number} containing corners and center of the given tensor.
     *
     * @since 1.0
     */
    public static Object[] cornersAndCenter(final Function<int[],Number> tensor, final int[] size, final int cornerSize) {
        /*
         * The 'source' array will contain indices of values to fetch in the tensor, and the 'target' array will contain
         * indices where to store those values in the returned data structure. Other arrays contain threshold indices of
         * points of interest in the target data structure.
         */
        final int sizeLimit = cornerSize*2 + 1;
        final int[] shown = size.clone();
        final int[] empty = size.clone();           // Target index of row/column to leave empty, or an unreachable value if none.
        for (int d=0; d<shown.length; d++) {
            if (shown[d] > sizeLimit) {
                shown[d] = sizeLimit;
                empty[d] = cornerSize;
            }
        }
        final int[] source = new int[shown.length];
        final int[] target = new int[shown.length];
        final Object[] numbers = (Object[]) Array.newInstance(Number.class, shown);
        /*
         * The loops below are used for simulating GOTO statements. This is usually a deprecated practice,
         * but in this case we can hardly use normal loops because the number of nested loops is dynamic.
         * We want something equivalent to the code below where 'n' - the number of nested loops - is not
         * known at compile-time:
         *
         * for (int i0=0; i0<size[0]; i0++) {
         *     for (int i1=0; i1<size[1]; i1++) {
         *         for (int i2=0; i2<size[2]; i2++) {
         *             // ... etc ...
         *             for (int in=0; in<size[n]; in++) {
         *             }
         *         }
         *     }
         * }
         *
         * Since we can not have a varying number of nested loops in the code, we achieve the same effect with
         * GOTO-like statements. It would be possible to achieve the same effect with recursive method calls,
         * but the GOTO-like approach is a little bit more compact.
         */
        Number[] row = null;
fill:   for (;;) {
            if (row == null) {
                Object[] walk = numbers;
                for (int d=shown.length; --d >= 1;) {
                    walk = (Object[]) walk[target[d]];
                }
                row = (Number[]) walk;
            }
            row[target[0]] = tensor.apply(source);
            for (int d=0;;) {
                source[d]++;
                final int p = ++target[d];
                if (p == shown[d]) {            // End of row (or higher dimension). This check must be first.
                    row = null;
                    source[d] = 0;
                    target[d] = 0;
                    if (++d >= shown.length) {
                        break fill;
                    }
                    // Continue loop for incrementing the higher dimension.
                } else {
                    switch (p - empty[d]) {
                        case 0:  continue;          // Column/row to leave null. Continue the loop for moving to next column/row.
                        case 1:  source[d] = size[d] - cornerSize;            // Skip source columns/rows (or higher dimensions).
                    }
                    continue fill;                  // Stop incrementing indices and fetch the value at current location.
                }
            }
        }
        /*
         * Add the center value in the empty location (in the middle).
         */
        Object walk = numbers;
        Object[] previous = null;
        for (int d=size.length; --d >= 0;) {
            previous = (Object[]) walk;
            walk = previous[empty[d]];
            source[d] = size[d] / 2;
        }
        if (walk == null) {
            previous[empty[0]] = tensor.apply(source);
        }
        return numbers;
    }
}
