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

import java.util.Map;
import java.util.Set;
import java.util.Collection;
import java.util.Collections;
import org.opengis.util.FactoryException;
import org.opengis.util.NoSuchIdentifierException;
import org.opengis.referencing.operation.Conversion;
import org.opengis.referencing.operation.Projection;
import org.opengis.referencing.operation.SingleOperation;
import org.opengis.referencing.operation.OperationMethod;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.parameter.ParameterValueGroup;
import org.apache.sis.parameter.Parameterized;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.operation.DefaultConversion;
import org.apache.sis.referencing.operation.matrix.Matrix2;
import org.apache.sis.referencing.crs.DefaultProjectedCRS;
import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
import org.apache.sis.internal.referencing.provider.Affine;
import org.apache.sis.internal.referencing.provider.Mercator1SP;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.measure.Units;

// Test dependencies
import org.apache.sis.referencing.cs.HardCodedCS;
import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.TestCase;
import org.junit.Test;

import static org.apache.sis.test.Assert.*;


/**
 * Tests the registration of operation methods in {@link DefaultMathTransformFactory}. This test uses the
 * providers registered in all {@code META-INF/services/org.opengis.referencing.operation.OperationMethod}
 * files found on the classpath.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.1
 * @since   0.6
 * @module
 */
@DependsOn({
    org.apache.sis.internal.referencing.provider.ProvidersTest.class,
    OperationMethodSetTest.class
})
public final strictfp class DefaultMathTransformFactoryTest extends TestCase {
    /**
     * Returns the factory to use for the tests.
     *
     * @return the factory to use for the tests.
     */
    static DefaultMathTransformFactory factory() {
        final MathTransformFactory factory = DefaultFactories.forClass(MathTransformFactory.class);
        assertNotNull("No Apache SIS implementation of MathTransformFactory found in “META-INF/services”.", factory);
        assertEquals("Expected the default implementation of MathTransformFactory to be first in “META-INF/services”.",
                DefaultMathTransformFactory.class, factory.getClass());
        return (DefaultMathTransformFactory) factory;
    }

    /**
     * Tests the {@link DefaultMathTransformFactory#getOperationMethod(String)} method.
     *
     * @throws NoSuchIdentifierException if the operation was not found.
     */
    @Test
    public void testGetOperationMethod() throws NoSuchIdentifierException {
        final DefaultMathTransformFactory factory = factory();
        final OperationMethod affine   = factory.getOperationMethod(Constants.AFFINE);
        final OperationMethod mercator = factory.getOperationMethod("Mercator (variant A)");

        assertInstanceOf("Affine",               Affine.class,      affine);
        assertInstanceOf("Mercator (variant A)", Mercator1SP.class, mercator);

        // Same than above, using EPSG code and alias.
        assertSame("EPSG:9624",    affine,   factory.getOperationMethod("EPSG:9624"));
        assertSame("EPSG:9804",    mercator, factory.getOperationMethod("EPSG:9804"));
        assertSame("Mercator_1SP", mercator, factory.getOperationMethod("Mercator_1SP"));
    }

    /**
     * Tests non-existent operation method.
     */
    @Test
    @DependsOnMethod("testGetOperationMethod")
    public void testNonExistentCode() {
        final DefaultMathTransformFactory factory = factory();
        try {
            factory.getOperationMethod("EPXX:9624");
            fail("Expected NoSuchIdentifierException");
        } catch (NoSuchIdentifierException e) {
            final String message = e.getLocalizedMessage();
            assertTrue(message, message.contains("EPXX:9624"));
        }
    }

    /**
     * Tests the {@link DefaultMathTransformFactory#getAvailableMethods(Class)} method.
     *
     * @throws NoSuchIdentifierException if the operation was not found.
     */
    @Test
    @DependsOnMethod("testGetOperationMethod")
    public void testGetAvailableMethods() throws NoSuchIdentifierException {
        final DefaultMathTransformFactory factory = factory();
        final Set<OperationMethod> transforms  = factory.getAvailableMethods(SingleOperation.class);
        final Set<OperationMethod> conversions = factory.getAvailableMethods(Conversion.class);
        final Set<OperationMethod> projections = factory.getAvailableMethods(Projection.class);
        /*
         * Following tests should not cause loading of more classes than needed.
         */
        assertFalse(transforms .isEmpty());
        assertFalse(conversions.isEmpty());
        assertFalse(projections.isEmpty());
        assertTrue (transforms.contains(factory.getOperationMethod(Constants.AFFINE)));
        /*
         * Following tests will force instantiation of all remaining OperationMethod.
         */
        assertTrue("Conversions should be a subset of transforms.",  transforms .containsAll(conversions));
        assertTrue("Projections should be a subset of conversions.", conversions.containsAll(projections));
    }

    /**
     * Asks for names which are known to be duplicated. One of the duplicated elements is deprecated.
     * However Apache SIS uses the same implementation.
     *
     * @throws NoSuchIdentifierException if the operation was not found.
     */
    @Test
    public void testDuplicatedNames() throws NoSuchIdentifierException {
        final DefaultMathTransformFactory factory = factory();
        final OperationMethod current    = factory.getOperationMethod("EPSG:1029");
        final OperationMethod deprecated = factory.getOperationMethod("EPSG:9823");
        assertSame(current, factory.getOperationMethod("Equidistant Cylindrical (Spherical)"));
        assertSame("Should share the non-deprecated implementation.", current, deprecated);
    }

    /**
     * Test {@link DefaultMathTransformFactory#createFromWKT(String)}. We test only a very small WKT here because
     * it is not the purpose of this class to test the parser. The main purpose of this test is to verify that
     * {@link DefaultMathTransformFactory} has been able to instantiate the parser.
     *
     * @throws FactoryException if the parsing failed.
     */
    @Test
    public void testCreateFromWKT() throws FactoryException {
        final MathTransform tr = factory().createFromWKT(
                "PARAM_MT[\"Affine\","
                    + "PARAMETER[\"num_row\",2],"
                    + "PARAMETER[\"num_col\",2],"
                    + "PARAMETER[\"elt_0_1\",7]]");

        assertMatrixEquals("Affine", new Matrix2(
                1, 7,
                0, 1), MathTransforms.getMatrix(tr), STRICT);
    }

    /**
     * Tests the creation of all registered map projections.
     * This test sets the semi-axis lengths and a few other mandatory parameter values.
     * For remaining parameters, we rely on default values.
     *
     * @throws FactoryException if the construction of a map projection failed.
     *
     * @since 0.7
     */
    @Test
    @SuppressWarnings("fallthrough")
    public void testAllMapProjections() throws FactoryException {
        /*
         * Gets all map projections and creates a projection using the WGS84 ellipsoid
         * and default parameter values.
         */
        final Map<String,?> dummyName = Collections.singletonMap(DefaultProjectedCRS.NAME_KEY, "Test");
        final MathTransformFactory mtFactory = DefaultFactories.forBuildin(MathTransformFactory.class);
        final Collection<OperationMethod> methods = mtFactory.getAvailableMethods(Projection.class);
        for (final OperationMethod method : methods) {
            final String classification = method.getName().getCode();
            ParameterValueGroup pg = mtFactory.getDefaultParameters(classification);
            pg.parameter("semi_major").setValue(6377563.396);
            pg.parameter("semi_minor").setValue(6356256.909237285);
            /*
             * Most parameters have default values, typically 0° or 0 metre, so we don't need to specify them for
             * the purpose of this test. But some map projections have mandatory parameters without default value.
             * In those cases, we must specify an arbitrary value otherwise the instantiation will fail.  When we
             * need to specify only one value, that value is remembered for opportunist verification.
             */
            String param = null;
            double value = Double.NaN;
            switch (classification) {
                case "Polar Stereographic (variant A)":           param = "Latitude of natural origin"; value = 90; break;
                case "Polar Stereographic (variant B)":
                case "Polar Stereographic (variant C)":           param = "Latitude of standard parallel"; value = 80; break;
                case "Hotine Oblique Mercator (variant A)":
                case "Hotine Oblique Mercator (variant B)":       param = "Azimuth of initial line"; value = 30; break;
                case "Lambert Conic Conformal (1SP)":
                case "Lambert Conic Conformal (West Orientated)": param = "Latitude of natural origin"; value = 45; break;
                case "Lambert Conic Conformal (2SP Michigan)":    param = "Ellipsoid scaling factor"; value = 1;  // Fall through for defining standard parallels too.
                case "Lambert Conic Conformal (2SP Belgium)":
                case "Lambert Conic Conformal (2SP)":
                case "Albers Equal Area": {
                    pg.parameter("Latitude of 1st standard parallel").setValue(30);
                    pg.parameter("Latitude of 2nd standard parallel").setValue(50);
                    break;
                }
                case "Hotine_Oblique_Mercator_Two_Point_Center":
                case "Hotine_Oblique_Mercator_Two_Point_Natural_Origin": {
                    pg.parameter( "Latitude_Of_1st_Point").setValue(30);
                    pg.parameter( "Latitude_Of_2nd_Point").setValue(50);
                    pg.parameter("Longitude_Of_1st_Point").setValue(10);
                    pg.parameter("Longitude_Of_2nd_Point").setValue(20);
                    break;
                }
                case "Satellite-Tracking": {
                    pg.parameter("satellite_orbit_inclination").setValue(  99.092);     // Landsat 1, 2 and 3.
                    pg.parameter("satellite_orbital_period")   .setValue( 103.267, Units.MINUTE);
                    pg.parameter("ascending_node_period")      .setValue(1440.0,   Units.MINUTE);
                    break;
                }
            }
            if (param != null) {
                pg.parameter(param).setValue(value);
            }
            final MathTransform mt;
            try {
                mt = mtFactory.createParameterizedTransform(pg);
            } catch (InvalidGeodeticParameterException e) {
                fail(classification + ": " + e.getLocalizedMessage());
                continue;
            }
            /*
             * Verifies that the map projection properties are the ones that we specified.
             * Note that the Equirectangular projection has been optimized as an affine transform, which we skip.
             */
            if (mt instanceof LinearTransform) {
                continue;
            }
            assertInstanceOf(classification, Parameterized.class, mt);
            pg = ((Parameterized) mt).getParameterValues();
            assertNotNull(classification, pg);
            assertEquals(classification, pg.getDescriptor().getName().getCode());
            assertEquals(classification, 6377563.396,       pg.parameter("semi_major").doubleValue(), 1E-4);
            assertEquals(classification, 6356256.909237285, pg.parameter("semi_minor").doubleValue(), 1E-4);
            if (param != null) {
                assertEquals(classification, value, pg.parameter(param).doubleValue(), 1E-4);
            }
            /*
             * Creates a ProjectedCRS from the map projection. This part is more an integration test than
             * a DefaultMathTransformFactory test. Again, the intent is to verify that the properties are
             * the one that we specified.
             */
            final DefaultProjectedCRS crs = new DefaultProjectedCRS(dummyName,
                    CommonCRS.WGS84.normalizedGeographic(),
                    new DefaultConversion(dummyName, method, mt, null),
                    HardCodedCS.PROJECTED);
            final Conversion projection = crs.getConversionFromBase();
            assertSame(classification, mt, projection.getMathTransform());
            assertEquals(classification, projection.getMethod().getName().getCode());
        }
    }
}
