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

import java.util.Date;
import java.util.Locale;
import java.util.Random;
import java.util.Collection;
import java.util.Map;
import java.lang.reflect.Method;
import org.opengis.util.CodeList;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.collection.CheckedContainer;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.metadata.Dependencies;
import org.apache.sis.test.xml.AnnotationConsistencyCheck;
import org.apache.sis.test.TestUtilities;
import org.apache.sis.test.DependsOn;
import org.junit.Test;


/**
 * Base class for tests done on metadata objects using reflection. This base class tests JAXB annotations
 * as described in the {@link AnnotationConsistencyCheck parent class}, and tests additional aspects like:
 *
 * <ul>
 *   <li>All {@link AbstractMetadata} instance shall be initially {@linkplain AbstractMetadata#isEmpty() empty}.</li>
 *   <li>All getter methods shall returns a null singleton or an empty collection, never a null collection.</li>
 *   <li>After a call to a setter method, the getter method shall return a value equals to the given value.</li>
 * </ul>
 *
 * This base class is defined in this {@code org.apache.sis.metadata} package because it needs to access
 * package-private classes.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.0
 * @since   0.3
 * @module
 */
@DependsOn(PropertyAccessorTest.class)
public abstract strictfp class PropertyConsistencyCheck extends AnnotationConsistencyCheck {
    /**
     * The standard implemented by the metadata objects to test.
     */
    private final MetadataStandard standard;

    /**
     * Random generator, or {@code null} if not needed.
     */
    private Random random;

    /**
     * Creates a new test suite for the given types.
     *
     * @param  standard  the standard implemented by the metadata objects to test.
     * @param  types     the GeoAPI interfaces, {@link CodeList} or {@link Enum} types to test.
     */
    protected PropertyConsistencyCheck(final MetadataStandard standard, final Class<?>... types) {
        super(types);
        this.standard = standard;
    }

    /**
     * Returns the SIS implementation for the given GeoAPI interface.
     *
     * @return {@inheritDoc}
     */
    @Override
    protected <T> Class<? extends T> getImplementation(final Class<T> type) {
        assertTrue(type.getName(), standard.isMetadata(type));
        final Class<? extends T> impl = standard.getImplementation(type);
        assertNotNull(type.getName(), impl);
        return impl;
    }

    /**
     * Return {@code true} if the given property is expected to be writable.
     * If this method returns {@code false}, then {@link #testPropertyValues()}
     * will not try to write a value for that property.
     *
     * <p>The default implementation returns {@code true}.</p>
     *
     * @param  impl      the implementation class.
     * @param  property  the name of the property to test.
     * @return {@code true} if the given property is writable.
     */
    protected boolean isWritable(final Class<?> impl, final String property) {
        return true;
    }

    /**
     * Returns a dummy value of the given type. The default implementation returns values for
     * {@link CharSequence}, {@link Number}, {@link Date}, {@link Locale}, {@link CodeList},
     * {@link Enum} and types in the {@link #types} list.
     *
     * <p>The returned value may be of an other type than the given one if the
     * {@code PropertyAccessor} converter method know how to convert that type.</p>
     *
     * @param  property  the name of the property for which to create a value.
     * @param  type      the type of value to create.
     * @return the value of the given {@code type}, or of a type convertible to the given type.
     */
    protected Object sampleValueFor(final String property, final Class<?> type) {
        if (CharSequence.class.isAssignableFrom(type)) {
            return "Dummy value for " + property + '.';
        }
        switch (Numbers.getEnumConstant(type)) {
            case Numbers.DOUBLE:  return         random.nextDouble() * 90;
            case Numbers.FLOAT:   return         random.nextFloat()  * 90f;
            case Numbers.LONG:    return (long)  random.nextInt(1000000) + 1;
            case Numbers.INTEGER: return         random.nextInt(  10000) + 1;
            case Numbers.SHORT:   return (short) random.nextInt(   1000) + 1;
            case Numbers.BYTE:    return (byte)  random.nextInt(    100) + 1;
            case Numbers.BOOLEAN: return         random.nextBoolean();
        }
        if (Date.class.isAssignableFrom(type)) {
            return new Date(random.nextInt() * 1000L);
        }
        if (CodeList.class.isAssignableFrom(type)) try {
            if (type == CodeList.class) {
                return null;
            }
            final CodeList<?>[] codes = (CodeList<?>[]) type.getMethod("values", (Class[]) null).invoke(null, (Object[]) null);
            return codes[random.nextInt(codes.length)];
        } catch (ReflectiveOperationException e) {
            fail(e.toString());
        }
        if (Locale.class.isAssignableFrom(type)) {
            switch (random.nextInt(4)) {
                case 0: return Locale.ROOT;
                case 1: return Locale.ENGLISH;
                case 2: return Locale.FRENCH;
                case 3: return Locale.JAPANESE;
            }
        }
        if (ArraysExt.containsIdentity(types, type)) {
            final Class<?> impl = getImplementation(type);
            if (impl != null) try {
                return impl.getConstructor((Class<?>[]) null).newInstance((Object[]) null);
            } catch (ReflectiveOperationException e) {
                fail(e.toString());
            }
        }
        return null;
    }

    /**
     * Normalizes the type of the given value before comparison. In particular, {@code InternationalString}
     * instances are converted to {@code String} instances.
     */
    private static Object normalizeType(Object value) {
        if (value instanceof CharSequence) {
            value = value.toString();
        }
        return value;
    }

    /**
     * Validates the given newly constructed metadata. The default implementation ensures that
     * {@link AbstractMetadata#isEmpty()} returns {@code true}.
     *
     * @param  metadata  the metadata to validate.
     */
    protected void validate(final AbstractMetadata metadata) {
        assertTrue("AbstractMetadata.isEmpty()", metadata.isEmpty());
    }

    /**
     * For every properties in every non-{@code Codelist} types listed in the {@link #types} array,
     * tests the property values. This method verifies that all {@link AbstractMetadata} instances
     * are initially {@linkplain AbstractMetadata#isEmpty() empty}, all getter methods return a null
     * singleton or an empty collection, and tests setting a random value.
     */
    @Test
    public void testPropertyValues() {
        random = TestUtilities.createRandomNumberGenerator();
        for (final Class<?> type : types) {
            if (!CodeList.class.isAssignableFrom(type)) {
                final Class<?> impl = getImplementation(type);
                if (impl != null) {
                    assertTrue("Not an implementation of expected interface.", type.isAssignableFrom(impl));
                    testPropertyValues(new PropertyAccessor(type, impl, impl));
                }
            }
        }
    }

    /**
     * Implementation of {@link #testPropertyValues()} for a single class.
     */
    private void testPropertyValues(final PropertyAccessor accessor) {
        /*
         * Try to instantiate the implementation. Every implementation should
         * have a no-args constructor, and their instantiation should never fail.
         */
        testingClass = accessor.implementation.getCanonicalName();
        final Object instance;
        try {
            instance = accessor.implementation.getConstructor((Class<?>[]) null).newInstance((Object[]) null);
        } catch (ReflectiveOperationException e) {
            fail(e.toString());
            return;
        }
        if (instance instanceof AbstractMetadata) {
            validate((AbstractMetadata) instance);
        }
        /*
         * Iterate over all properties defined in the interface,
         * and checks for the existences of a setter method.
         */
        final int count = accessor.count();
        for (int i=0; i<count; i++) {
            testingMethod = accessor.name(i, KeyNamePolicy.METHOD_NAME);
            if (skipTest(accessor.implementation, testingMethod)) {
                continue;
            }
            final String property = accessor.name(i, KeyNamePolicy.JAVABEANS_PROPERTY);
            assertNotNull("Missing method name.", testingMethod);
            assertNotNull("Missing property name.", property);
            assertEquals("Wrong property index.", i, accessor.indexOf(property, true));
            /*
             * Get the property type. In the special case where the property type
             * is a collection, this is the type of elements in that collection.
             */
            final Class<?> propertyType = Numbers.primitiveToWrapper(accessor.type(i, TypeValuePolicy.PROPERTY_TYPE));
            final Class<?>  elementType = Numbers.primitiveToWrapper(accessor.type(i, TypeValuePolicy.ELEMENT_TYPE));
            assertNotNull(testingMethod, propertyType);
            assertNotNull(testingMethod, elementType);
            final boolean isMap        =        Map.class.isAssignableFrom(propertyType);
            final boolean isCollection = Collection.class.isAssignableFrom(propertyType);
            assertFalse("Element type can not be Collection.", Collection.class.isAssignableFrom(elementType));
            assertEquals("Property and element types shall be the same if and only if not a collection.",
                         !(isMap | isCollection), propertyType == elementType);
            /*
             * Try to get a value.
             */
            Object value = accessor.get(i, instance);
            if (value == null) {
                assertFalse("Null values are not allowed to be collections.", isMap | isCollection);
            } else {
                assertTrue("Wrong property type.", propertyType.isInstance(value));
                if (value instanceof CheckedContainer<?>) {
                    assertTrue("Wrong element type in collection.",
                            elementType.isAssignableFrom(((CheckedContainer<?>) value).getElementType()));
                }
                if (isMap) {
                    assertTrue("Collections shall be initially empty.", ((Map<?,?>) value).isEmpty());
                    value = CollectionsExt.modifiableCopy((Map<?,?>) value);                          // Protect from changes.
                } else if (isCollection) {
                    assertTrue("Collections shall be initially empty.", ((Collection<?>) value).isEmpty());
                    value = CollectionsExt.modifiableCopy((Collection<?>) value);                     // Protect from changes.
                }
            }
            /*
             * Try to write a value.
             */
            final boolean isWritable = isWritable(accessor.implementation, property);
            if (isWritable != accessor.isWritable(i)) {
                fail("Non writable property: " + accessor + '.' + property);
            }
            if (isWritable) {
                if (Date.class.isAssignableFrom(accessor.type(i, TypeValuePolicy.ELEMENT_TYPE))) {
                    // Dates requires sis-temporal module, which is not available for sis-metadata.
                    continue;
                }
                if (isMap) {
                    continue;
                }
                final Object newValue = sampleValueFor(property, elementType);
                final Object oldValue = accessor.set(i, instance, newValue, PropertyAccessor.RETURN_PREVIOUS);
                assertEquals("PropertyAccessor.set(…) shall return the value previously returned by get(…).", value, oldValue);
                value = accessor.get(i, instance);
                if (isCollection) {
                    if (newValue == null) {
                        assertTrue("We did not generated a random value for this type, consequently the "
                                + "collection should still empty.", ((Collection<?>) value).isEmpty());
                        value = null;
                    } else {
                        value = TestUtilities.getSingleton((Collection<?>) value);
                    }
                }
                assertEquals("PropertyAccessor.get(…) shall return the value that we have just set.",
                        normalizeType(newValue), normalizeType(value));
            }
        }
    }

    /**
     * Returns {@code true} if test for the given property should be skipped.
     * Reasons for skipping a test are:
     *
     * <ul>
     *   <li>Class which is a union (those classes behave differently than non-union classes).</li>
     *   <li>Method which is the delegate of many legacy ISO 19115:2003 methods.
     *       Having a property that can be modified by many other properties confuse the tests.</li>
     * </ul>
     */
    @SuppressWarnings("deprecation")
    private static boolean skipTest(final Class<?> implementation, final String method) {
        return implementation == org.apache.sis.metadata.iso.maintenance.DefaultScopeDescription.class ||
              (implementation == org.apache.sis.metadata.iso.citation.DefaultResponsibleParty.class &&
               method.equals("getParties"));
    }

    /**
     * Verifies the {@link TitleProperty} annotations. This method verifies that the property exist,
     * is a singleton, and is not another metadata object. The property should also be mandatory,
     * but this method does not verify that restriction since there is some exceptions.
     *
     * @since 0.8
     */
    @Test
    public void testTitlePropertyAnnotation() {
        for (final Class<?> type : types) {
            final Class<?> impl = standard.getImplementation(type);
            if (impl != null) {
                final TitleProperty an = impl.getAnnotation(TitleProperty.class);
                if (an != null) {
                    final String name = an.name();
                    final String message = impl.getSimpleName() + '.' + name;
                    final PropertyAccessor accessor = new PropertyAccessor(type, impl, impl);

                    // Property shall exist.
                    final int index = accessor.indexOf(name, false);
                    assertTrue(message, index >= 0);

                    // Property can not be a metadata.
                    final Class<?> elementType = accessor.type(index, TypeValuePolicy.ELEMENT_TYPE);
                    assertFalse(message, standard.isMetadata(elementType));

                    // Property shall be a singleton.
                    assertSame(message, elementType, accessor.type(index, TypeValuePolicy.PROPERTY_TYPE));
                }
            }
        }
    }

    /**
     * Verifies the {@link Dependencies} annotations. This method verifies that the annotation is applied on
     * deprecated getter methods, that the referenced properties exist and the getter methods of referenced
     * properties are not deprecated.
     *
     * @throws NoSuchMethodException if {@link PropertyAccessor} references a non-existent method (would be a bug).
     *
     * @since 0.8
     */
    @Test
    public void testDependenciesAnnotation() throws NoSuchMethodException {
        for (final Class<?> type : types) {
            final Class<?> impl = standard.getImplementation(type);
            if (impl != null) {
                Map<String,String> names = null;
                for (final Method method : impl.getDeclaredMethods()) {
                    final Dependencies dep = method.getAnnotation(Dependencies.class);
                    if (dep != null) {
                        final String name = method.getName();
                        if (names == null) {
                            names = standard.asNameMap(type, KeyNamePolicy.JAVABEANS_PROPERTY, KeyNamePolicy.METHOD_NAME);
                        }
                        /*
                         * Currently, @Dependencies is applied only on deprecated getter methods.
                         * However this policy may change in future Apache SIS versions.
                         */
                        assertTrue(name, name.startsWith("get"));
                        assertTrue(name, method.isAnnotationPresent(Deprecated.class));
                        /*
                         * All dependencies shall be non-deprecated methods. Combined with above
                         * restriction about @Dependencies applied only on deprected methods, this
                         * ensure that there is no cycle.
                         */
                        for (final String ref : dep.value()) {
                            // Verify that the dependency is a property name.
                            assertEquals(name, names.get(ref), ref);

                            // Verify that the referenced method is non-deprecated.
                            assertFalse(name, impl.getMethod(names.get(ref)).isAnnotationPresent(Deprecated.class));
                        }
                    }
                }
            }
        }
    }
}
