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

import java.util.Arrays;
import java.util.Random;
import java.io.IOException;
import java.io.LineNumberReader;
import org.opengis.util.FactoryException;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.internal.referencing.Formulas;
import org.apache.sis.internal.referencing.provider.TransverseMercatorSouth;
import org.apache.sis.referencing.operation.transform.CoordinateDomain;
import org.apache.sis.parameter.Parameters;
import org.apache.sis.util.CharSequences;
import org.apache.sis.test.OptionalTestData;
import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.DependsOn;
import org.junit.Test;

import static java.lang.Double.NaN;
import static java.lang.StrictMath.min;
import static java.lang.StrictMath.toRadians;
import static org.apache.sis.test.Assert.*;
import static org.apache.sis.internal.referencing.provider.TransverseMercator.LATITUDE_OF_ORIGIN;
import org.opengis.test.CalculationType;


/**
 * Tests the {@link TransverseMercator} class.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.0
 * @since   0.6
 * @module
 */
@DependsOn(NormalizedProjectionTest.class)
public final strictfp class TransverseMercatorTest extends MapProjectionTestCase {
    /**
     * Creates a new instance of {@link TransverseMercator}.
     *
     * @param  ellipsoidal  {@code false} for a sphere, or {@code true} for WGS84 ellipsoid.
     */
    private void createNormalizedProjection(final boolean ellipsoidal, final double latitudeOfOrigin) {
        final org.apache.sis.internal.referencing.provider.TransverseMercator method =
                new org.apache.sis.internal.referencing.provider.TransverseMercator();
        final Parameters parameters = parameters(method, ellipsoidal);
        parameters.getOrCreate(LATITUDE_OF_ORIGIN).setValue(latitudeOfOrigin);
        transform = new TransverseMercator(method, parameters);
        tolerance = NORMALIZED_TOLERANCE;
        validate();
    }

    /**
     * Tests the <cite>Transverse Mercator</cite> case (EPSG:9807).
     * This test is defined in GeoAPI conformance test suite.
     *
     * @throws FactoryException if an error occurred while creating the map projection.
     * @throws TransformException if an error occurred while projecting a coordinate.
     *
     * @see org.opengis.test.referencing.ParameterizedTransformTest#testTransverseMercator()
     */
    @Test
    public void testTransverseMercator() throws FactoryException, TransformException {
        createGeoApiTest(new org.apache.sis.internal.referencing.provider.TransverseMercator()).testTransverseMercator();
    }

    /**
     * Tests the <cite>Transverse Mercator (South Orientated)</cite> case (EPSG:9808).
     * This test is defined in GeoAPI conformance test suite.
     *
     * @throws FactoryException if an error occurred while creating the map projection.
     * @throws TransformException if an error occurred while projecting a coordinate.
     *
     * @see org.opengis.test.referencing.ParameterizedTransformTest#testTransverseMercatorSouthOrientated()
     */
    @Test
    @DependsOnMethod("testTransverseMercator")
    public void testTransverseMercatorSouthOrientated() throws FactoryException, TransformException {
        createGeoApiTest(new TransverseMercatorSouth()).testTransverseMercatorSouthOrientated();
    }

    /**
     * Verifies the consistency of elliptical formulas with the spherical formulas.
     * This test compares the results of elliptical formulas with the spherical ones
     * for some random points.
     *
     * @throws FactoryException if an error occurred while creating the map projection.
     * @throws TransformException if an error occurred while projecting a coordinate.
     */
    @Test
    @DependsOnMethod("testTransverseMercator")
    public void compareEllipticalWithSpherical() throws FactoryException, TransformException {
        createCompleteProjection(new org.apache.sis.internal.referencing.provider.TransverseMercator(),
                6371007,    // Semi-major axis length
                6371007,    // Semi-minor axis length
                0.5,        // Central meridian
                2.5,        // Latitude of origin
                NaN,        // Standard parallel 1 (none)
                NaN,        // Standard parallel 2 (none)
                0.997,      // Scale factor
                200,        // False easting
                100);       // False northing
        tolerance = Formulas.LINEAR_TOLERANCE;
        compareEllipticalWithSpherical(CoordinateDomain.RANGE_10, 0);
    }

    /**
     * Creates a projection and derivates a few points.
     *
     * @throws TransformException if an error occurred while projecting a point.
     */
    @Test
    public void testSphericalDerivative() throws TransformException {
        createNormalizedProjection(false, 0);
        tolerance = 1E-9;

        final double delta = toRadians(100.0 / 60) / 1852;      // Approximately 100 metres.
        derivativeDeltas = new double[] {delta, delta};
        verifyDerivative(toRadians( 0), toRadians( 0));
        verifyDerivative(toRadians(-3), toRadians(30));
        verifyDerivative(toRadians(+6), toRadians(60));
    }

    /**
     * Creates a projection and derivates a few points.
     *
     * @throws TransformException if an error occurred while projecting a point.
     */
    @Test
    public void testEllipsoidalDerivative() throws TransformException {
        createNormalizedProjection(true, 0);
        tolerance = 1E-9;

        final double delta = toRadians(100.0 / 60) / 1852;      // Approximately 100 metres.
        derivativeDeltas = new double[] {delta, delta};
        verifyDerivative(toRadians( 0), toRadians( 0));
        verifyDerivative(toRadians(-3), toRadians(30));
        verifyDerivative(toRadians(+6), toRadians(60));
    }

    /**
     * Verifies that deserialized projections work as expected. This implies that deserialization
     * recomputed the internal transient fields, especially the series expansion coefficients.
     *
     * @throws FactoryException if an error occurred while creating the map projection.
     * @throws TransformException if an error occurred while projecting a coordinate.
     */
    @Test
    @DependsOnMethod("testTransverseMercator")
    public void testSerialization() throws FactoryException, TransformException {
        createNormalizedProjection(true, 40);
        /*
         * Use a fixed seed for the random number generator in this test, because in case of failure this class will not
         * report which seed it used. This limitation exists because this test class does not extend the SIS TestCase.
         */
        final double[] source = CoordinateDomain.GEOGRAPHIC_RADIANS_HALF_λ.generateRandomInput(new Random(5346144739450824145L), 2, 10);
        final double[] target = new double[source.length];
        for (int i=0; i<source.length; i+=2) {
            // A longitude range of [-90 … +90]° is still too wide for Transverse Mercator. Reduce to [-45 … +45]°.
            source[i] /= 2;
        }
        transform.transform(source, 0, target, 0, 10);
        transform = assertSerializedEquals(transform);
        tolerance = Formulas.LINEAR_TOLERANCE;
        verifyTransform(source, target);
    }

    /**
     * Compares with <cite>Karney (2009) Test data for the transverse Mercator projection</cite>.
     * This is an optional test executed only if the {@code $SIS_DATA/Tests/TMcoords.dat} file is found.
     *
     * @throws IOException if an error occurred while reading the test file.
     * @throws FactoryException if an error occurred while creating the map projection.
     * @throws TransformException if an error occurred while transforming coordinates.
     */
    @Test
    public void compareAgainstDataset() throws IOException, FactoryException, TransformException {
        try (LineNumberReader reader = OptionalTestData.TRANSVERSE_MERCATOR.reader()) {
            createCompleteProjection(new org.apache.sis.internal.referencing.provider.TransverseMercator(),
                    WGS84_A,    // Semi-major axis length
                    WGS84_B,    // Semi-minor axis length
                    0,          // Central meridian
                    0,          // Latitude of origin
                    NaN,        // Standard parallel 1 (none)
                    NaN,        // Standard parallel 2 (none)
                    0.9996,     // Scale factor
                    0,          // False easting
                    0);         // False northing
            final double[] source = new double[2];
            final double[] target = new double[2];
            String line;
            while ((line = reader.readLine()) != null) {
                Arrays.fill(source, Double.NaN);
                final CharSequence[] split = CharSequences.split(line, ' ');
                for (int i=min(split.length, 4); --i >= 0;) {
                    final double value = Double.parseDouble(split[i].toString());
                    if (i <= 1) source[i ^ 1] = value;                              // Swap axis order.
                    else        target[i - 2] = value;
                }
                // Relax tolerance for longitudes very far from central meridian.
                final double longitude = StrictMath.abs(source[0]);
                if (longitude < TransverseMercator.DOMAIN_OF_VALIDITY) {
                    if (StrictMath.abs(source[1]) >= 89.9) tolerance = 0.1;
                    else if (longitude <= 60) tolerance = Formulas.LINEAR_TOLERANCE;
                    else if (longitude <= 66) tolerance = 0.1;
                    else if (longitude <= 70) tolerance = 1;
                    else if (longitude <= 72) tolerance = 2;
                    else if (longitude <= 74) tolerance = 10;
                    else if (longitude <= 76) tolerance = 30;
                    else                      tolerance = 1000;
                    transform.transform(source, 0, source, 0, 1);
                    assertCoordinateEquals(line, target, source, reader.getLineNumber(), CalculationType.DIRECT_TRANSFORM);
                }
            }
        }
    }
}
