/*
 * 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.referencing.ReferenceIdentifier;
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, ReferenceIdentifier.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);
        }
    }
}
