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

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.lang.reflect.Array;
import javax.xml.bind.annotation.XmlElementRef;
import org.opengis.util.GenericName;
import org.opengis.metadata.Identifier;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.GeneralParameterDescriptor;
import org.opengis.parameter.ParameterNotFoundException;
import org.apache.sis.parameter.AbstractParameterDescriptor;
import org.apache.sis.parameter.DefaultParameterDescriptor;
import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
import org.apache.sis.parameter.DefaultParameterValueGroup;
import org.apache.sis.parameter.Parameters;
import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.util.collection.Containers;
import org.apache.sis.util.CorruptedObjectException;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.jaxb.gco.PropertyType;
import org.apache.sis.internal.jaxb.Context;


/**
 * JAXB adapter mapping implementing class to the GeoAPI interface. See
 * package documentation for more information about JAXB and interface.
 *
 * <p>This class provides additional {@code merge(…)} methods for building a unique descriptor
 * instance when the same descriptor is declared in more than one place in the GML document.
 * Some examples of duplications are:</p>
 *
 * <ul>
 *   <li>The descriptors listed under the {@code <gml:group>} element, which duplicate the descriptors listed
 *       under each {@code <gml:parameterValue>} element.</li>
 *   <li>The descriptors declared in each parameter value of a {@code SingleOperation}, which duplicate the
 *       descriptors declared in the associated {@code OperationMethod}.</li>
 * </ul>
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.6
 * @since   0.6
 * @module
 */
public final class CC_GeneralOperationParameter extends PropertyType<CC_GeneralOperationParameter, GeneralParameterDescriptor> {
    /**
     * The default value of {@code minimumOccurs} and {@code maximumOccurs} if the XML element is not provided.
     */
    public static final short DEFAULT_OCCURRENCE = 1;

    /**
     * The properties to ignore in the descriptor parsed from GML when this descriptor is merged with a
     * pre-defined descriptor. Remarks:
     *
     * <ul>
     *   <li>We ignore the name because the comparisons shall be performed by the caller with
     *       {@link IdentifiedObjects#isHeuristicMatchForName} or something equivalent.</li>
     *   <li>We ignore aliases and identifiers because they are collections, which require
     *       handling in a special way.</li>
     * </ul>
     */
    private static final String[] IGNORE_DURING_MERGE = {
        GeneralParameterDescriptor.NAME_KEY,
        GeneralParameterDescriptor.ALIAS_KEY,
        GeneralParameterDescriptor.IDENTIFIERS_KEY
    };

    /**
     * Empty constructor for JAXB only.
     */
    public CC_GeneralOperationParameter() {
    }

    /**
     * Returns the GeoAPI interface which is bound by this adapter.
     * This method is indirectly invoked by the private constructor
     * below, so it shall not depend on the state of this object.
     *
     * @return {@code GeneralParameterDescriptor.class}
     */
    @Override
    protected Class<GeneralParameterDescriptor> getBoundType() {
        return GeneralParameterDescriptor.class;
    }

    /**
     * Constructor for the {@link #wrap} method only.
     */
    private CC_GeneralOperationParameter(final GeneralParameterDescriptor parameter) {
        super(parameter);
    }

    /**
     * Invoked by {@link PropertyType} at marshalling time for wrapping the given value in a
     * {@code <gml:OperationParameter>} or {@code <gml:OperationParameterGroup>} XML element.
     *
     * @param  parameter  the element to marshal.
     * @return a {@code PropertyType} wrapping the given the element.
     */
    @Override
    protected CC_GeneralOperationParameter wrap(final GeneralParameterDescriptor parameter) {
        return new CC_GeneralOperationParameter(parameter);
    }

    /**
     * Invoked by JAXB at marshalling time for getting the actual element to write
     * inside the {@code <gml:parameter>} XML element.
     * This is the value or a copy of the value given in argument to the {@code wrap} method.
     *
     * @return the element to be marshalled.
     *
     * @see CC_GeneralParameterValue#getElement()
     */
    @XmlElementRef
    public AbstractParameterDescriptor getElement() {
        final GeneralParameterDescriptor metadata = this.metadata;
        if (metadata instanceof AbstractParameterDescriptor) {
            return (AbstractParameterDescriptor) metadata;
        }
        if (metadata instanceof ParameterDescriptor) {
            return DefaultParameterDescriptor.castOrCopy((ParameterDescriptor<?>) metadata);
        }
        if (metadata instanceof ParameterDescriptorGroup) {
            return DefaultParameterDescriptorGroup.castOrCopy((ParameterDescriptorGroup) metadata);
        }
        return null;    // Unknown types are currently not marshalled (we may revisit that in a future SIS version).
    }

    /**
     * Invoked by JAXB at unmarshalling time for storing the result temporarily.
     *
     * @param  parameter  the unmarshalled element.
     */
    public void setElement(final AbstractParameterDescriptor parameter) {
        metadata = parameter;
    }

    /**
     * Verifies that the given descriptor is non-null and contains at least a name.
     * This method is used after unmarshalling.
     */
    static boolean isValid(final GeneralParameterDescriptor descriptor) {
        return descriptor != null && descriptor.getName() != null;
    }

    /**
     * Returns {@code true} if the given descriptor is restricted to a constant value.
     * This constraint exists in some pre-defined map projections.
     *
     * <div class="note"><b>Example:</b>
     * the <cite>"Latitude of natural origin"</cite> parameter of <cite>"Mercator (1SP)"</cite> projection
     * is provided for completeness, but should never be different than zero in this particular projection
     * (otherwise it would be a <cite>"Mercator (variant C)"</cite> projection).  But if this parameter is
     * nevertheless provided, the SIS implementation will use it. From this point of view, SIS is tolerant
     * to non-zero value.
     *
     * <p>If the GML document declares explicitly a restricted parameter, maybe it intends to use it with
     * a non-zero value. Consequently the {@code merge(…)} method will not propagate this restriction.</p>
     * </div>
     */
    private static boolean isRestricted(final ParameterDescriptor<?> descriptor) {
        final Comparable<?> min = descriptor.getMinimumValue();
        if (min instanceof Number) {
            final Comparable<?> max = descriptor.getMaximumValue();
            if (max instanceof Number) {
                // Compare as 'double' because we want (-0 == +0) to be true.
                return ((Number) min).doubleValue() == ((Number) max).doubleValue();
            }
        }
        return false;
    }

    /**
     * Returns a descriptor with the same properties than the {@code provided} one, but completed with information
     * not found in GML. Those missing information are given by the {@code complete} descriptor, which may come from
     * two sources:
     *
     * <ul>
     *   <li>The descriptor for a {@code <gml:ParameterValue>} element. Those descriptors are more complete than the
     *       ones provided by {@code <gml:OperationParameter>} elements alone because the parameter value allows SIS
     *       to infer the {@code valueClass}.</li>
     *   <li>A pre-defined parameter descriptor from the {@link org.apache.sis.internal.referencing.provider} package.</li>
     * </ul>
     *
     * @param  provided  the descriptor unmarshalled from the GML document.
     * @param  complete  the descriptor to use for completing missing information.
     * @return the descriptor to use. May be one of the arguments given to this method, or a new instance.
     *
     * @see <a href="http://issues.apache.org/jira/browse/SIS-290">SIS-290</a>
     */
    static GeneralParameterDescriptor merge(final GeneralParameterDescriptor provided,
                                            final GeneralParameterDescriptor complete)
    {
        if (provided == complete) {
            return complete;
        }
        final boolean isGroup;
        if (provided instanceof ParameterDescriptor<?> && complete instanceof ParameterDescriptor<?>) {
            isGroup = false;    // This is by far the most usual case.
        } else if (provided instanceof ParameterDescriptorGroup && complete instanceof ParameterDescriptorGroup) {
            isGroup = true;
        } else {
            /*
             * Mismatched or unknown type. It should not happen with descriptors parsed by JAXB and with
             * pre-defined descriptors provided by SIS. But it could happen with a pre-defined descriptor
             * found in a user-provided OperationMethod with malformed parameters.
             * Return the descriptor found in the GML document as-is.
             */
            return provided;
        }
        final int minimumOccurs = provided.getMinimumOccurs();
        final int maximumOccurs = provided.getMaximumOccurs();
        final Map<String,?> expected = IdentifiedObjects.getProperties(complete);
        final Map<String,?> actual   = IdentifiedObjects.getProperties(provided, IGNORE_DURING_MERGE);
        final boolean canSubstitute  = complete.getMinimumOccurs() == minimumOccurs
                                    && complete.getMaximumOccurs() == maximumOccurs
                                    && expected.entrySet().containsAll(actual.entrySet())
                                    && containsAll(complete.getAlias(), provided.getAlias())
                                    && containsAll(complete.getIdentifiers(), provided.getIdentifiers());
        if (canSubstitute && !isGroup) {
            /*
             * The pre-defined or ParameterValue descriptor contains at least all the information found
             * in the descriptor parsed from the GML document. We can use the existing instance directly,
             * assuming that the additional properties are acceptable.
             *
             * We make an exception to the above rule if the existing instance put a possibly too strong
             * restriction on the parameter values. See 'isRestricted(…)' for more information.
             */
            if (!isRestricted((ParameterDescriptor<?>) complete)) {
                return complete;
            }
        }
        /*
         * Collect the properties specified in the GML document and complete with the properties provided
         * by the 'complete' descriptor. If the descriptor is a group, then this 'replacement' method will
         * be invoked recursively for each parameter in the group.
         */
        final Map<String,Object> merged = new HashMap<>(expected);
        merged.putAll(actual);  // May overwrite pre-defined properties.
        mergeArrays(GeneralParameterDescriptor.ALIAS_KEY,       GenericName.class, provided.getAlias(),       merged, complete.getName());
        mergeArrays(GeneralParameterDescriptor.IDENTIFIERS_KEY, Identifier.class,  provided.getIdentifiers(), merged, null);
        if (isGroup) {
            final List<GeneralParameterDescriptor> descriptors = ((ParameterDescriptorGroup) provided).descriptors();
            return merge(DefaultParameterValueGroup.class, merged, merged, minimumOccurs, maximumOccurs,
                    descriptors.toArray(new GeneralParameterDescriptor[descriptors.size()]),
                    (ParameterDescriptorGroup) complete, canSubstitute);
        } else {
            return create(merged, (ParameterDescriptor<?>) provided, (ParameterDescriptor<?>) complete);
        }
    }

    /**
     * Returns a descriptor with the given properties, completed with information not found in GML.
     * Those extra information are given by the {@code complete} descriptor.
     *
     * @param  caller         the public source class to report if a log message need to be emitted.
     * @param  properties     properties as declared in the GML document, to be used if {@code complete} is incompatible.
     * @param  merged         more complete properties, to be used if {@code complete} is compatible.
     * @param  minimumOccurs  value to assign to {@link DefaultParameterDescriptorGroup#getMinimumOccurs()}.
     * @param  maximumOccurs  value to assign to {@link DefaultParameterDescriptorGroup#getMaximumOccurs()}.
     * @param  provided       parameter descriptors declared in the GML document. This array will be overwritten.
     * @param  complete       more complete parameter descriptors.
     * @param  canSubstitute  {@code true} if this method is allowed to return {@code complete}.
     * @return the parameter descriptor group to use (may be the {@code complete} instance).
     *
     * @see <a href="http://issues.apache.org/jira/browse/SIS-290">SIS-290</a>
     */
    static ParameterDescriptorGroup merge(final Class<?>                     caller,
                                          final Map<String,?>                properties,
                                          final Map<String,?>                merged,
                                          final int                          minimumOccurs,
                                          final int                          maximumOccurs,
                                          final GeneralParameterDescriptor[] provided,
                                          final ParameterDescriptorGroup     complete,
                                          boolean                            canSubstitute)
    {
        boolean isCompatible = true;
        final Set<GeneralParameterDescriptor> included = new HashSet<>(Containers.hashMapCapacity(provided.length));
        for (int i=0; i<provided.length; i++) {
            final GeneralParameterDescriptor p = provided[i];
            try {
                /*
                 * Replace the descriptors provided in the GML document by descriptors from the 'complete' instance,
                 * if possible. Keep trace of the complete descriptors that we found in this process.
                 */
                GeneralParameterDescriptor predefined = complete.descriptor(p.getName().getCode());
                if (predefined != null) {   // Safety in case 'complete' is a user's implementation.
                    canSubstitute &= (provided[i] = merge(p, predefined)) == predefined;
                    if (!included.add(predefined)) {
                        throw new CorruptedObjectException(predefined);  // Broken hashCode/equals, or object mutated.
                    }
                    continue;
                }
            } catch (ParameterNotFoundException e) {
                /*
                 * Log at Level.WARNING for the first parameter (canSubstitute == true) and at Level.FINE
                 * for all other (canSubstitute == false).  We do not use CC_GeneralOperationParameter as
                 * the source class because this is an internal class. We rather use the first public class
                 * in the caller hierarchy, which is either DefaultParameterValueGroup or DefaultOperationMethod.
                 */
                Context.warningOccured(Context.current(), caller,
                        (caller == DefaultParameterValueGroup.class) ? "setValues" : "setDescriptors", e, canSubstitute);
            }
            /*
             * If a parameter was not found in the 'complete' descriptor, we will not be able to use that descriptor.
             * But we may still be able to use its properties (name, alias, identifier) provided that the parameter
             * not found was optional.
             */
            isCompatible &= p.getMinimumOccurs() == 0;
            canSubstitute = false;
        }
        if (isCompatible) {
            /*
             * At this point, we determined that all mandatory parameters in the GML document exist in the 'complete'
             * descriptor. However the converse is not necessarily true. Verify that all parameters missing in the GML
             * document were optional.
             */
            for (final GeneralParameterDescriptor descriptor : complete.descriptors()) {
                if (!included.contains(descriptor) && descriptor.getMinimumOccurs() != 0
                        && !CC_OperationMethod.isImplicitParameter(descriptor))
                {
                    canSubstitute = false;
                    isCompatible  = false;
                    break;
                }
            }
        }
        if (canSubstitute) {
            return complete;
        } else {
            return new DefaultParameterDescriptorGroup(isCompatible ? merged : properties,
                    minimumOccurs, maximumOccurs, provided);
        }
    }

    /**
     * Creates a new descriptor with the same properties than the {@code provided} one, but completed with
     * information not found in GML. Those extra information are given by the {@code complete} descriptor.
     *
     * <p>It is the caller's responsibility to construct the {@code merged} properties as a merge of the properties
     * of the two given descriptors. This can be done with the help of {@link #mergeArrays(String, Class, Collection,
     * Map, Identifier)} among others.</p>
     */
    private static <T> ParameterDescriptor<T> create(final Map<String,?>          merged,
                                                     final ParameterDescriptor<?> provided,
                                                     final ParameterDescriptor<T> complete)
    {
        final Class<T> valueClass = complete.getValueClass();
        return new DefaultParameterDescriptor<>(merged,
                provided.getMinimumOccurs(),
                provided.getMaximumOccurs(),
                // Values below this point are not provided in GML documents,
                // so they must be inferred from the pre-defined descriptor.
                valueClass,
                Parameters.getValueDomain(complete),
                CollectionsExt.toArray(complete.getValidValues(), valueClass),
                complete.getDefaultValue());
    }

    /**
     * Returns {@code true} if the {@code complete} collection contains all elements in the {@code provided}
     * collection, where each element have been converted to the canonical {@link NamedIdentifier} implementation
     * for comparison purpose.
     *
     * @param  <T>       the type of elements in the collection.
     * @param  complete  the collection which is expected to contains all elements.
     * @param  provided  the collection which may be a subset of {@code complete}.
     * @return {@code true} if {@code complete} contains all {@code provided} elements.
     */
    private static <T> boolean containsAll(final Collection<T> complete, final Collection<T> provided) {
        if (!provided.isEmpty()) {
            final int size = complete.size();
            if (size == 0) {
                return false;
            }
            final Set<NamedIdentifier> c = new HashSet<>(Containers.hashMapCapacity(size));
            for (final T e : complete) {
                c.add(toNamedIdentifier(e));
            }
            for (final T e : provided) {
                if (!c.contains(toNamedIdentifier(e))) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Merges the property of type {@code Collection} identified by the given key.
     * This is used when we can not just substitute one collection by the other.
     *
     * @param <T>            the type of elements in the array or collection.
     * @param key            the key where to fetch or store the array in the {@code merged} map.
     * @param componentType  the type of elements in the array or collection.
     * @param provided       the elements unmarshalled from the XML document.
     * @param merged         the map used for completing missing information.
     */
    @SuppressWarnings("unchecked")
    private static <T> void mergeArrays(final String key, final Class<T> componentType,
            Collection<T> provided, final Map<String,Object> merged, final Identifier remove)
    {
        if (!provided.isEmpty()) {
            T[] complete = (T[]) merged.get(key);
            if (complete != null) {
                /*
                 * Add the 'provided' values before 'complete' for two reasons:
                 *   1) Use the same insertion order than the declaration order in the GML file.
                 *   2) Replace 'provided' instances by 'complete' instances, since the later
                 *      are sometime pre-defined instances defined as static final constants.
                 */
                final Map<NamedIdentifier,T> c = new LinkedHashMap<>();
                for (final T e : provided) c.put(toNamedIdentifier(e), e);
                for (final T e : complete) c.put(toNamedIdentifier(e), e);
                c.remove(toNamedIdentifier(remove));
                provided = c.values();
            }
            complete = provided.toArray((T[]) Array.newInstance(componentType, provided.size()));
            merged.put(key, complete);
        }
    }

    /**
     * Given an {@link Identifier} or {@link GenericName} instance, returns that instance as a {@link NamedIdentifier}
     * implementation. The intent is to allow {@code Object.equals(Object)} and hash code to correctly recognize two
     * names or identifiers as equal even if they are of different implementations.
     *
     * <p>Note that {@link NamedIdentifier} is the type of unmarshalled names, aliases and identifiers.
     * So this method should not create any new object in a majority of cases.</p>
     */
    private static NamedIdentifier toNamedIdentifier(final Object name) {
        if (name == null || name.getClass() == NamedIdentifier.class) {
            return (NamedIdentifier) name;
        } else if (name instanceof Identifier) {
            return new NamedIdentifier((Identifier) name);
        } else {
            return new NamedIdentifier((GenericName) name);
        }
    }
}
