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

import java.util.Map;
import java.util.HashMap;
import java.util.IdentityHashMap;
import org.opengis.util.GenericName;
import org.opengis.metadata.Identifier;
import org.opengis.parameter.GeneralParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.referencing.operation.OperationMethod;
import org.apache.sis.referencing.operation.DefaultOperationMethod;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.TestCase;
import org.junit.Test;

import static org.junit.Assert.*;


/**
 * Tests {@link Providers} and some consistency rules of all providers defined in this package.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.1
 * @since   0.6
 * @module
 */
@DependsOn({
    org.apache.sis.referencing.operation.DefaultOperationMethodTest.class,
    AffineTest.class,
    LongitudeRotationTest.class,
    MapProjectionTest.class
})
public final strictfp class ProvidersTest extends TestCase {
    /**
     * Returns all providers to test.
     */
    private static Class<?>[] methods() {
        return new Class<?>[] {
            Affine.class,
            AxisOrderReversal.class,
            AxisOrderReversal3D.class,
            GeographicOffsets.class,
            GeographicOffsets2D.class,
            GeographicAndVerticalOffsets.class,
            VerticalOffset.class,
            LongitudeRotation.class,
            CoordinateFrameRotation.class,
            CoordinateFrameRotation2D.class,
            CoordinateFrameRotation3D.class,
            PositionVector7Param.class,
            PositionVector7Param2D.class,
            PositionVector7Param3D.class,
            GeocentricTranslation.class,
            GeocentricTranslation2D.class,
            GeocentricTranslation3D.class,
            GeographicToGeocentric.class,
            GeocentricToGeographic.class,
            Geographic3Dto2D.class,
            Geographic2Dto3D.class,
            Molodensky.class,
            AbridgedMolodensky.class,
            PseudoPlateCarree.class,
            Equirectangular.class,
            Mercator1SP.class,
            Mercator2SP.class,
            MercatorSpherical.class,
            PseudoMercator.class,
            RegionalMercator.class,
            MillerCylindrical.class,
            LambertConformal1SP.class,
            LambertConformal2SP.class,
            LambertConformalWest.class,
            LambertConformalBelgium.class,
            LambertConformalMichigan.class,
            LambertCylindricalEqualArea.class,
            LambertCylindricalEqualAreaSpherical.class,
            AlbersEqualArea.class,
            TransverseMercator.class,
            TransverseMercatorSouth.class,
            PolarStereographicA.class,
            PolarStereographicB.class,
            PolarStereographicC.class,
            PolarStereographicNorth.class,
            PolarStereographicSouth.class,
            ObliqueStereographic.class,
            ObliqueMercator.class,
            ObliqueMercatorCenter.class,
            ObliqueMercatorTwoPoints.class,
            ObliqueMercatorTwoPointsCenter.class,
            ZonedTransverseMercator.class,
            SatelliteTracking.class,
            Sinusoidal.class,
            Polyconic.class,
            Mollweide.class,
            NTv2.class,
            NADCON.class,
            FranceGeocentricInterpolation.class,
            MolodenskyInterpolation.class,
            Interpolation1D.class
        };
    }

    /**
     * Returns the subset of {@link #methods()} which are expected to support
     * {@link AbstractProvider#redimension(int, int)}, not including map projections.
     */
    private static Class<?>[] redimensionables() {
        return new Class<?>[] {
            Affine.class,
            LongitudeRotation.class,
            GeographicOffsets.class,
            GeographicOffsets2D.class,
            GeographicAndVerticalOffsets.class,
            CoordinateFrameRotation2D.class,
            CoordinateFrameRotation3D.class,
            PositionVector7Param2D.class,
            PositionVector7Param3D.class,
            GeocentricTranslation2D.class,
            GeocentricTranslation3D.class,
            Geographic3Dto2D.class,
            Geographic2Dto3D.class,
            Molodensky.class,
            AbridgedMolodensky.class,
            FranceGeocentricInterpolation.class
        };
    }

    /**
     * Ensures that every parameter instance is unique. Actually this test is not strong requirement.
     * This is only for sharing existing resources by avoiding unnecessary objects duplication.
     *
     * @throws ReflectiveOperationException if the instantiation of a service provider failed.
     */
    @Test
    public void ensureParameterUniqueness() throws ReflectiveOperationException {
        final Map<GeneralParameterDescriptor, String> groupNames = new IdentityHashMap<>();
        final Map<GeneralParameterDescriptor, GeneralParameterDescriptor> parameters = new HashMap<>();
        final Map<Object, Object> namesAndIdentifiers = new HashMap<>();
        for (final Class<?> c : methods()) {
            final OperationMethod method = (OperationMethod) c.newInstance();
            final ParameterDescriptorGroup group = method.getParameters();
            final String operationName = group.getName().getCode();
            for (final GeneralParameterDescriptor param : group.descriptors()) {
                assertFalse("Parameter declared twice in the same group.",
                        operationName.equals(groupNames.put(param, operationName)));
                /*
                 * Ensure uniqueness of the parameter descriptor as a whole.
                 */
                final Identifier name = param.getName();
                Object existing = parameters.put(param, param);
                if (existing != null && existing != param) {
                    fail("Parameter “" + name.getCode() + "” defined in “" + operationName + '”'
                            + " was already defined in “" + groupNames.get(existing) + "”."
                            + " The same instance could be shared.");
                }
                /*
                 * Ensure uniqueness of each name and identifier.
                 */
                existing = namesAndIdentifiers.put(name, name);
                if (existing != null && existing != name) {
                    fail("The name of parameter “" + name.getCode() + "” defined in “" + operationName + '”'
                            + " was already defined elsewhere. The same instance could be shared.");
                }
                for (final GenericName alias : param.getAlias()) {
                    existing = namesAndIdentifiers.put(alias, alias);
                    if (existing != null && existing != alias) {
                        fail("Alias “" + alias + "” of parameter “" + name.getCode() + "” defined in “" + operationName + '”'
                                + " was already defined elsewhere. The same instance could be shared.");
                    }
                }
                for (final Identifier id : param.getIdentifiers()) {
                    existing = namesAndIdentifiers.put(id, id);
                    if (existing != null && existing != id) {
                        fail("Identifier “" + id + "” of parameter “" + name.getCode() + "” defined in “" + operationName + '”'
                                + " was already defined elsewhere. The same instance could be shared.");
                    }
                }
            }
        }
    }

    /**
     * Tests {@link AbstractProvider#redimension(int, int)} on all providers managed by {@link Providers}.
     */
    @Test
    public void testRedimension() {
        final Map<Class<?>,Boolean> redimensionables = new HashMap<>(100);
        for (final Class<?> type : methods()) {
            assertNull(type.getName(), redimensionables.put(type, Boolean.FALSE));
        }
        for (final Class<?> type : redimensionables()) {
            assertEquals(type.getName(), Boolean.FALSE, redimensionables.put(type, Boolean.TRUE));
        }
        final Providers providers = new Providers();
        for (final OperationMethod method : providers) {
            if (method instanceof ProviderMock) {
                continue;                           // Skip the methods that were defined only for test purpose.
            }
            final int sourceDimensions = method.getSourceDimensions();
            final int targetDimensions = method.getTargetDimensions();
            final Boolean isRedimensionable = redimensionables.get(method.getClass());
            assertNotNull(method.getClass().getName(), isRedimensionable);
            if (isRedimensionable) {
                for (int newSource = 2; newSource <= 3; newSource++) {
                    for (int newTarget = 2; newTarget <= 3; newTarget++) {
                        final OperationMethod redim = ((DefaultOperationMethod) method).redimension(newSource, newTarget);
                        assertEquals("sourceDimensions", newSource, redim.getSourceDimensions().intValue());
                        assertEquals("targetDimensions", newTarget, redim.getTargetDimensions().intValue());
                        if (!(method instanceof Affine)) {
                            if (newSource == sourceDimensions && newTarget == targetDimensions) {
                                assertSame("When asking the original number of dimensions, expected the original instance.", method, redim);
                            } else {
                                assertNotSame("When asking a different number of dimensions, expected a different instance.", method, redim);
                            }
                            assertSame("When asking the original number of dimensions, expected the original instance.",
                                    method, ((DefaultOperationMethod) redim).redimension(sourceDimensions, targetDimensions));
                        }
                    }
                }
            } else if (method instanceof MapProjection) {
                final OperationMethod proj3D = ((MapProjection) method).redimension(sourceDimensions ^ 1, targetDimensions ^ 1);
                assertNotSame("redimension(3,3) should return a new method.", method, proj3D);
                assertSame("redimension(2,2) should give back the original method.", method,
                        ((DefaultOperationMethod) proj3D).redimension(sourceDimensions, targetDimensions));
                assertSame("Value of redimension(3,3) should have been cached.", proj3D,
                        ((MapProjection) method).redimension(sourceDimensions ^ 1, targetDimensions ^ 1));
            } else try {
                ((DefaultOperationMethod) method).redimension(sourceDimensions ^ 1, targetDimensions ^ 1);
                fail("Type " + method.getClass().getName() + " is not in our list of redimensionable methods.");
            } catch (IllegalArgumentException e) {
                final String message = e.getMessage();
                assertTrue(message, message.contains(method.getName().getCode()));
            }
        }
    }

    /**
     * Tests the description provided in some parameters.
     */
    @Test
    public void testDescription() {
        assertFalse(SatelliteTracking.SATELLITE_ORBIT_INCLINATION.getDescription().length() == 0);
        assertFalse(SatelliteTracking.SATELLITE_ORBITAL_PERIOD   .getDescription().length() == 0);
        assertFalse(SatelliteTracking.ASCENDING_NODE_PERIOD      .getDescription().length() == 0);
    }
}
