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

import java.util.Collection;
import java.util.Collections;
import org.opengis.util.GenericName;
import org.opengis.util.InternationalString;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.maintenance.ScopeCode;
import org.opengis.metadata.quality.DataQuality;
import org.opengis.metadata.quality.EvaluationMethodType;
import org.apache.sis.metadata.iso.quality.AbstractElement;
import org.apache.sis.metadata.iso.quality.DefaultDataQuality;
import org.apache.sis.metadata.iso.quality.DefaultDomainConsistency;
import org.apache.sis.metadata.iso.quality.DefaultConformanceResult;
import org.apache.sis.metadata.iso.quality.DefaultScope;
import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.util.resources.Errors;

// Branch-dependent imports
import org.opengis.feature.Property;
import org.opengis.feature.PropertyType;
import org.opengis.feature.Attribute;
import org.opengis.feature.AttributeType;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
import org.opengis.feature.FeatureAssociation;
import org.opengis.feature.FeatureAssociationRole;


/**
 * Provides validation methods to be shared by different implementations.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.7
 * @since   0.5
 * @module
 */
final class Validator {
    /**
     * The data quality report.
     */
    final DefaultDataQuality quality;

    /**
     * Creates a new validator.
     *
     * @param scope  {@code FEATURE} if the object to validate is a feature, or
     *               {@code ATTRIBUTE} for an attribute, or {@code null} otherwise.
     */
    Validator(final ScopeCode scope) {
        quality = new DefaultDataQuality();
        if (scope != null) {
            quality.setScope(new DefaultScope(scope));
        }
    }

    /**
     * Adds a report for a constraint violation. If the given {@code report} is {@code null}, then this method creates
     * a new {@link DefaultDomainConsistency} instance with the measure identification set to the property name.
     *
     * <div class="note"><b>Note:</b>
     * setting {@code measureIdentification} to the property name may look like a departure from ISO intent,
     * since the former should be an identification of the <em>quality measurement</em> rather then the measure itself.
     * (setting {@code measureDescription} to {@code type.getDescription()} would probably be wrong for that reason).
     * However {@code measureIdentification} is only an identifier, not a full description of the quality measurement
     * We are not strictly forbidden to use the same identifier for both the quality measurement than the measurement
     * itself. However strictly speaking, maybe we should use a different scope.</div>
     *
     * @param  report       where to add the result, or {@code null} if not yet created.
     * @param  type         description of the property for which a constraint violation has been found.
     * @param  explanation  explanation of the constraint violation.
     * @return the {@code report}, or a new report if {@code report} was null.
     */
    private AbstractElement addViolationReport(AbstractElement report,
            final PropertyType type, final InternationalString explanation)
    {
        if (report == null) {
            final GenericName name = type.getName();
            report = new DefaultDomainConsistency();
            // Do not invoke report.setMeasureDescription(type.getDescription()) - see above javadoc.
            report.setMeasureIdentification(name instanceof Identifier ? (Identifier) name : new NamedIdentifier(name));
            report.setEvaluationMethodType(EvaluationMethodType.DIRECT_INTERNAL);
            quality.getReports().add(report);
        }
        report.getResults().add(new DefaultConformanceResult(null, explanation, false));
        return report;
    }

    /**
     * Wraps singleton value in a collection for processing by {@code validate(…)} methods.
     */
    private static Collection<?> asList(final Object value, final int maximumOccurrences) {
        if (maximumOccurrences <= 1) {
            return (value != null) ? Collections.singletonList(value) : Collections.emptyList();
        } else {
            return (Collection<?>) value;
        }
    }

    /**
     * Implementation of {@link AbstractFeature#quality()}, also shared by {@link Features} static method.
     *
     * @param type     the type of the {@code feature} argument, provided explicitly for protecting from user overriding.
     * @param feature  the feature to validate.
     */
    void validate(final FeatureType type, final Feature feature) {
        for (final PropertyType pt : type.getProperties(true)) {
            final Property property = feature.getProperty(pt.getName().toString());
            final DataQuality pq;
            if (property instanceof AbstractAttribute<?>) {
                pq = ((AbstractAttribute<?>) property).quality();
            } else if (property instanceof AbstractAssociation) {
                pq = ((AbstractAssociation) property).quality();
            } else if (property instanceof Attribute<?>) {
                validate(((Attribute<?>) property).getType(), ((Attribute<?>) property).getValues());
                continue;
            } else if (property instanceof FeatureAssociation) {
                validate(((FeatureAssociation) property).getRole(), ((FeatureAssociation) property).getValues());
                continue;
            } else {
                continue;
            }
            if (pq != null) {                                          // Should not be null, but let be safe.
                quality.getReports().addAll(pq.getReports());
            }
        }
    }

    /**
     * Verifies if the given value is valid for the given attribute type.
     * This method delegates to one of the {@code validate(…)} methods depending of the value type.
     */
    void validateAny(final PropertyType type, final Object value) {
        if (type instanceof AttributeType<?>) {
            validate((AttributeType<?>) type, asList(value,
                    ((AttributeType<?>) type).getMaximumOccurs()));
        }
        if (type instanceof FeatureAssociationRole) {
            validate((FeatureAssociationRole) type, asList(value,
                    ((FeatureAssociationRole) type).getMaximumOccurs()));
        }
    }

    /**
     * Verifies if the given values are valid for the given attribute type.
     */
    void validate(final AttributeType<?> type, final Collection<?> values) {
        AbstractElement report = null;
        for (final Object value : values) {
            /*
             * In theory, the following check is unnecessary since the type was constrained by the Attribute.setValue(V)
             * method signature. However in practice the call to Attribute.setValue(…) is sometime done after type erasure,
             * so we are better to check.
             */
            final Class<?> valueClass = type.getValueClass();
            if (!valueClass.isInstance(value)) {
                report = addViolationReport(report, type, Errors.formatInternational(
                        Errors.Keys.IllegalPropertyValueClass_3, type.getName(), valueClass, value.getClass()));

                // Report only the first violation for now.
                break;
            }
        }
        verifyCardinality(report, type, type.getMinimumOccurs(), type.getMaximumOccurs(), values.size());
    }

    /**
     * Verifies if the given value is valid for the given association role.
     */
    void validate(final FeatureAssociationRole role, final Collection<?> values) {
        AbstractElement report = null;
        for (final Object value : values) {
            final FeatureType type = ((Feature) value).getType();
            final FeatureType valueType = role.getValueType();
            if (!valueType.isAssignableFrom(type)) {
                report = addViolationReport(report, role, Errors.formatInternational(
                        Errors.Keys.IllegalPropertyValueClass_3, role.getName(), valueType.getName(), type.getName()));

                // Report only the first violation for now.
                break;
            }
        }
        verifyCardinality(report, role, role.getMinimumOccurs(), role.getMaximumOccurs(), values.size());
    }

    /**
     * Verifies if the given value is compliant with the cardinality constraint.
     *
     * @param report  where to add the result, or {@code null} if not yet created.
     */
    private void verifyCardinality(final AbstractElement report, final PropertyType type,
            final int minimumOccurs, final int maximumOccurs, final int count)
    {
        if (count < minimumOccurs) {
            final InternationalString message;
            if (count == 0) {
                message = Errors.formatInternational(Errors.Keys.MissingValueForProperty_1, type.getName());
            } else {
                message = Errors.formatInternational(Errors.Keys.TooFewOccurrences_2, minimumOccurs, type.getName());
            }
            addViolationReport(report, type, message);
        } else if (count > maximumOccurs) {
            final InternationalString message;
            if (maximumOccurs == 0) {
                message = Errors.formatInternational(Errors.Keys.ForbiddenProperty_1, type.getName());
            } else {
                message = Errors.formatInternational(Errors.Keys.TooManyOccurrences_2, maximumOccurs, type.getName());
            }
            addViolationReport(report, type, message);
        }
    }
}
