/*
 * 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.Map;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.io.Serializable;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.InvalidObjectException;
import java.io.IOException;
import org.opengis.util.GenericName;
import org.opengis.metadata.quality.DataQuality;
import org.opengis.metadata.maintenance.ScopeCode;
import org.apache.sis.util.Classes;
import org.apache.sis.util.ArgumentChecks;


/**
 * An instance of an {@linkplain DefaultAttributeType attribute type} containing the value of an attribute in a feature.
 * {@code Attribute} holds three main information:
 *
 * <ul>
 *   <li>A {@linkplain #getType() reference to an attribute type}
 *       which defines the base Java type and domain of valid values.</li>
 *   <li>One or more {@linkplain #getValues() values}, which may be a singleton ([0 … 1] multiplicity)
 *       or multi-valued ([0 … ∞] multiplicity).</li>
 *   <li>Optional {@linkplain #characteristics() characteristics} about the attribute
 *       (e.g. a <var>temperature</var> attribute may have a characteristic holding the measurement <var>accuracy</var>).
 *       Characteristics are often, but not necessarily, constant for all attributes of the same type in a dataset.</li>
 * </ul>
 *
 * {@code AbstractAttribute} can be instantiated by calls to {@link DefaultAttributeType#newInstance()}.
 *
 * <div class="section">Limitations</div>
 * <ul>
 *   <li><b>Multi-threading:</b> {@code AbstractAttribute} instances are <strong>not</strong> thread-safe.
 *       Synchronization, if needed, shall be done externally by the caller.</li>
 *   <li><b>Serialization:</b> serialized objects of this class are not guaranteed to be compatible with future
 *       versions. Serialization should be used only for short term storage or RMI between applications running
 *       the same SIS version.</li>
 *   <li><b>Cloning:</b> despite providing a public {@link #clone()} method, this base class is <strong>not</strong>
 *       cloneable by default. Subclasses shall implement the {@link Cloneable} interface themselves if they choose
 *       to support cloning.</li>
 * </ul>
 *
 * @author  Johann Sorel (Geomatys)
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.8
 *
 * @param <V>  the type of attribute values.
 *
 * @see AbstractFeature
 * @see DefaultAttributeType
 *
 * @since 0.5
 * @module
 */
@SuppressWarnings("CloneInNonCloneableClass")       // Decision left to subclasses - see javadoc
public abstract class AbstractAttribute<V> extends Field<V> implements Serializable {
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = 7442739120526654676L;

    /**
     * Information about the attribute (base Java class, domain of values, <i>etc.</i>).
     */
    final DefaultAttributeType<V> type;

    /**
     * Other attributes that describes this attribute, or {@code null} if not yet created.
     *
     * <div class="note"><b>Design note:</b>
     * We could question if it is a good idea to put this field here, given that this field add a slight cost
     * to all attribute implementations while only a small fraction of them will want attribute characteristics.
     * Since attributes may exist in a very large amount, that question may be significant.
     * However {@link AbstractFeature} tries hard to not create {@code Attribute} instances at all (it tries to
     * store only their value instead), so we presume that peoples who ask for {@code Attribute} instances are
     * willing to accept their cost.</div>
     *
     * @see #characteristics()
     */
    private transient Map<String,AbstractAttribute<?>> characteristics;

    /**
     * Creates a new attribute of the given type.
     *
     * @param type  information about the attribute (base Java class, domain of values, <i>etc.</i>).
     *
     * @see #create(DefaultAttributeType)
     */
    protected AbstractAttribute(final DefaultAttributeType<V> type) {
        this.type = type;
    }

    /**
     * Creates a new attribute of the given type initialized to the
     * {@linkplain DefaultAttributeType#getDefaultValue() default value}.
     *
     * @param  <V>   the type of attribute values.
     * @param  type  information about the attribute (base Java class, domain of values, <i>etc.</i>).
     * @return the new attribute.
     *
     * @see DefaultAttributeType#newInstance()
     */
    public static <V> AbstractAttribute<V> create(final DefaultAttributeType<V> type) {
        ArgumentChecks.ensureNonNull("type", type);
        return isSingleton(type.getMaximumOccurs())
               ? new SingletonAttribute<>(type)
               : new MultiValuedAttribute<>(type);
    }

    /**
     * Creates a new attribute of the given type initialized to the given value.
     * Note that a {@code null} value may not be the same as the default value.
     *
     * @param  <V>    the type of attribute values.
     * @param  type   information about the attribute (base Java class, domain of values, <i>etc.</i>).
     * @param  value  the initial value (may be {@code null}).
     * @return the new attribute.
     */
    static <V> AbstractAttribute<V> create(final DefaultAttributeType<V> type, final Object value) {
        ArgumentChecks.ensureNonNull("type", type);
        return isSingleton(type.getMaximumOccurs())
               ? new SingletonAttribute<>(type, value)
               : new MultiValuedAttribute<>(type, value);
    }

    /**
     * Invoked on serialization for saving the {@link #characteristics} field.
     *
     * @param  out  the output stream where to serialize this attribute.
     * @throws IOException if an I/O error occurred while writing.
     */
    private void writeObject(final ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        final AbstractAttribute<?>[] characterizedBy;
        if (characteristics instanceof CharacteristicMap) {
            characterizedBy = characteristics.values().toArray(new AbstractAttribute<?>[characteristics.size()]);
        } else {
            characterizedBy = null;
        }
        out.writeObject(characterizedBy);
    }

    /**
     * Invoked on deserialization for restoring the {@link #characteristics} field.
     *
     * @param  in  the input stream from which to deserialize an attribute.
     * @throws IOException if an I/O error occurred while reading or if the stream contains invalid data.
     * @throws ClassNotFoundException if the class serialized on the stream is not on the classpath.
     */
    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        try {
            final AbstractAttribute<?>[] characterizedBy = (AbstractAttribute<?>[]) in.readObject();
            if (characterizedBy != null) {
                characteristics = newCharacteristicsMap();
                characteristics.values().addAll(Arrays.asList(characterizedBy));
            }
        } catch (RuntimeException e) {
            // At least ClassCastException, NullPointerException, IllegalArgumentException and IllegalStateException.
            throw (IOException) new InvalidObjectException(e.getLocalizedMessage()).initCause(e);
        }
    }

    /**
     * Returns the name of this attribute as defined by its {@linkplain #getType() type}.
     * This convenience method delegates to {@link DefaultAttributeType#getName()}.
     *
     * @return the attribute name specified by its type.
     */
    @Override
    public GenericName getName() {
        return type.getName();
    }

    /**
     * Returns information about the attribute (base Java class, domain of values, <i>etc.</i>).
     *
     * <div class="warning"><b>Warning:</b> In a future SIS version, the return type may be changed
     * to {@code org.opengis.feature.AttributeType}. This change is pending GeoAPI revision.</div>
     *
     * @return information about the attribute.
     */
    public DefaultAttributeType<V> getType() {
        return type;
    }

    /**
     * Returns the attribute value, or {@code null} if none. This convenience method can be invoked in
     * the common case where the {@linkplain DefaultAttributeType#getMaximumOccurs() maximum number}
     * of attribute values is restricted to 1 or 0.
     *
     * @return the attribute value (may be {@code null}).
     * @throws IllegalStateException if this attribute contains more than one value.
     *
     * @see AbstractFeature#getPropertyValue(String)
     */
    @Override
    public abstract V getValue() throws IllegalStateException;

    /**
     * Returns all attribute values, or an empty collection if none.
     * The returned collection is <cite>live</cite>: changes in the returned collection
     * will be reflected immediately in this {@code Attribute} instance, and conversely.
     *
     * <p>The default implementation returns a collection which will delegate its work to
     * {@link #getValue()} and {@link #setValue(Object)}.</p>
     *
     * @return the attribute values in a <cite>live</cite> collection.
     */
    @Override
    public Collection<V> getValues() {
        return super.getValues();
    }

    /**
     * Sets the attribute value. All previous values are replaced by the given singleton.
     *
     * <div class="section">Validation</div>
     * The amount of validation performed by this method is implementation dependent.
     * Usually, only the most basic constraints are verified. This is so for performance reasons
     * and also because some rules may be temporarily broken while constructing a feature.
     * A more exhaustive verification can be performed by invoking the {@link #quality()} method.
     *
     * @param  value  the new value, or {@code null} for removing all values from this attribute.
     * @throws IllegalArgumentException if this method verifies argument validity and the given value
     *         does not met the attribute constraints.
     *
     * @see AbstractFeature#setPropertyValue(String, Object)
     */
    @Override
    public abstract void setValue(final V value) throws IllegalArgumentException;

    /**
     * Sets the attribute values. All previous values are replaced by the given collection.
     *
     * <p>The default implementation ensures that the given collection contains at most one element,
     * then delegates to {@link #setValue(Object)}.</p>
     *
     * @param  values  the new values.
     * @throws IllegalArgumentException if the given collection contains too many elements.
     */
    @Override
    public void setValues(final Collection<? extends V> values) throws IllegalArgumentException {
        super.setValues(values);
    }

    /**
     * Other attributes that describes this attribute. For example if this attribute carries a measurement,
     * then a characteristic of this attribute could be the measurement accuracy.
     * See <cite>"Attribute characterization"</cite> in {@link DefaultAttributeType} Javadoc for more information.
     *
     * <p>The map returned by this method contains only the characteristics explicitly defined for this attribute.
     * If the map contains no characteristic for a given name, a {@linkplain DefaultAttributeType#getDefaultValue()
     * default value} may still exist.
     * In such cases, callers may also need to inspect the {@link DefaultAttributeType#characteristics()}
     * as shown in the <cite>Reading a characteristic</cite> section below.</p>
     *
     * <div class="note"><b>Rational:</b>
     * Very often, all attributes of a given type in the same dataset have the same characteristics.
     * For example it is very common that all temperature measurements in a dataset have the same accuracy,
     * and setting a different accuracy for a single measurement is relatively rare.
     * Consequently, {@code characteristics.isEmpty()} is a convenient way to check that an attribute have
     * all the "standard" characteristics and need no special processing.</div>
     *
     * <div class="section">Reading a characteristic</div>
     * The characteristic values are enumerated in the {@linkplain Map#values() map values}.
     * The {@linkplain Map#keySet() map keys} are the {@code String} representations of characteristics
     * {@linkplain DefaultAttributeType#getName() name}, for more convenient lookups.
     *
     * <p>If an attribute is known to be a measurement with a characteristic named "accuracy"
     * of type {@link Float}, then the accuracy value could be read as below:</p>
     *
     * {@preformat java
     *     Float getAccuracy(Attribute<?> measurement) {
     *         Attribute<?> accuracy = measurement.characteristics().get("accuracy");
     *         if (accuracy != null) {
     *             return (Float) accuracy.getValue(); // Value may be null.
     *         } else {
     *             return (Float) measurement.getType().characteristics().get("accuracy").getDefaultValue();
     *             // A more sophisticated implementation would probably cache the default value somewhere.
     *         }
     *     }
     * }
     *
     * <div class="section">Adding a characteristic</div>
     * A new characteristic can be added in the map in three different ways:
     * <ol>
     *   <li>Putting the (<var>name</var>, <var>characteristic</var>) pair explicitly.
     *     If an older characteristic existed for that name, it will be replaced.
     *     Example:
     *
     *     {@preformat java
     *       Attribute<?> accuracy = ...;                               // To be created by the caller.
     *       characteristics.put("accuracy", accuracy);
     *     }</li>
     *
     *   <li>Adding the new characteristic to the {@linkplain Map#values() values} collection.
     *     The name is inferred automatically from the characteristic type.
     *     If an older characteristic existed for the same name, an {@link IllegalStateException} will be thrown.
     *     Example:
     *
     *     {@preformat java
     *       Attribute<?> accuracy = ...;                               // To be created by the caller.
     *       characteristics.values().add(accuracy);
     *     }</li>
     *
     *   <li>Adding the characteristic name to the {@linkplain Map#keySet() key set}.
     *     If no characteristic existed for that name, a default one will be created.
     *     Example:
     *
     *     {@preformat java
     *       characteristics.keySet().add("accuracy");                  // Ensure that an entry will exist for that name.
     *       Attribute<?> accuracy = characteristics.get("accuracy");
     *       Features.cast(accuracy, Float.class).setValue(...);        // Set new accuracy value here as a float.
     *     }</li>
     * </ol>
     *
     * @return other attribute types that describes this attribute type, or an empty map if none.
     *
     * @see DefaultAttributeType#characteristics()
     */
    @SuppressWarnings("ReturnOfCollectionOrArrayField")
    public Map<String,AbstractAttribute<?>> characteristics() {
        if (characteristics == null) {
            characteristics = newCharacteristicsMap();
        }
        return characteristics;                                 // Intentionally modifiable
    }

    /**
     * Creates an initially empty map of characteristics for this attribute.
     * This method does not store the new map in the {@link #characteristics} field;
     * it is caller responsibility to do so if desired.
     */
    private Map<String,AbstractAttribute<?>> newCharacteristicsMap() {
        if (type instanceof DefaultAttributeType<?>) {
            Map<String, DefaultAttributeType<?>> map = type.characteristics();
            if (!map.isEmpty()) {
                if (!(map instanceof CharacteristicTypeMap)) {
                    final Collection<DefaultAttributeType<?>> types = map.values();
                    map = CharacteristicTypeMap.create(type, types.toArray(new DefaultAttributeType<?>[types.size()]));
                }
                return new CharacteristicMap(this, (CharacteristicTypeMap) map);
            }
        }
        return Collections.emptyMap();
    }

    /**
     * Returns the characteristics, or an empty map if the characteristics have not yet been built.
     * Contrarily to {@link #characteristics()}, this method does not create the map. This method
     * is suitable when then caller only wants to read the map and does not plan to write anything.
     */
    final Map<String,AbstractAttribute<?>> characteristicsReadOnly() {
        return (characteristics != null) ? characteristics : Collections.emptyMap();
    }

    /**
     * Evaluates the quality of this attribute at this method invocation time. The data quality reports
     * may include information about whether the attribute value mets the constraints defined by the
     * {@linkplain DefaultAttributeType attribute type}, or any other criterion at implementation choice.
     *
     * <p>The default implementation reports data quality with at least the following information:</p>
     * <ul>
     *   <li>
     *     The {@linkplain org.apache.sis.metadata.iso.quality.DefaultDataQuality#getScope() scope}
     *     {@linkplain org.apache.sis.metadata.iso.quality.DefaultScope#getLevel() level} is set to
     *     {@link org.opengis.metadata.maintenance.ScopeCode#ATTRIBUTE}.
     *   </li><li>
     *     At most one {@linkplain org.apache.sis.metadata.iso.quality.DefaultDomainConsistency domain consistency}
     *     element is added to the {@linkplain org.apache.sis.metadata.iso.quality.DefaultDataQuality#getReports()
     *     reports} list (implementations are free to omit that element if they have nothing to report).
     *     If a report is provided, then it will contain at least the following information:
     *     <ul>
     *       <li>
     *         <p>The {@linkplain #getName() attribute name} as the data quality
     *         {@linkplain org.apache.sis.metadata.iso.quality.DefaultDomainConsistency#getMeasureIdentification()
     *         measure identification}.</p>
     *
     *         <div class="note"><b>Note:</b> strictly speaking, {@code measureIdentification} identifies the
     *         <em>quality measurement</em>, not the “real” measurement itself. However this implementation
     *         uses the same set of identifiers for both for simplicity.</div>
     *       </li><li>
     *         <p>If the attribute {@linkplain #getValue() value} is not an {@linkplain Class#isInstance instance}
     *         of the expected {@linkplain DefaultAttributeType#getValueClass() value class}, or if the number
     *         of occurrences is not inside the multiplicity range, or if any other constraint is violated, then
     *         a {@linkplain org.apache.sis.metadata.iso.quality.DefaultConformanceResult conformance result} is
     *         added for each violation with an
     *         {@linkplain org.apache.sis.metadata.iso.quality.DefaultConformanceResult#getExplanation() explanation}
     *         set to the error message.</p>
     *
     *         <div class="warning"><b>Note:</b> this is a departure from ISO intent, since {@code explanation}
     *         should be a statement about what a successful conformance means. This point may be reformulated
     *         in a future SIS version.</div>
     *       </li>
     *     </ul>
     *   </li>
     * </ul>
     *
     * This attribute is valid if this method does not report any
     * {@linkplain org.apache.sis.metadata.iso.quality.DefaultConformanceResult conformance result} having a
     * {@linkplain org.apache.sis.metadata.iso.quality.DefaultConformanceResult#pass() pass} value of {@code false}.
     *
     * <div class="note"><b>Example:</b> given an attribute named “population” with [1 … 1] multiplicity,
     * if no value has been assigned to that attribute, then this {@code quality()} method will return
     * the following data quality report:
     *
     * {@preformat text
     *   Data quality
     *     ├─Scope
     *     │   └─Level………………………………………………… Attribute
     *     └─Report
     *         ├─Measure identification
     *         │   └─Code………………………………………… population
     *         ├─Evaluation method type…… Direct internal
     *         └─Result
     *             ├─Explanation……………………… Missing value for “population” property.
     *             └─Pass………………………………………… false
     * }
     * </div>
     *
     * @return reports on all constraint violations found.
     *
     * @see AbstractFeature#quality()
     */
    public DataQuality quality() {
        final Validator v = new Validator(ScopeCode.ATTRIBUTE);
        v.validate(type, getValues());
        return v.quality;
    }

    /**
     * Returns a string representation of this attribute.
     * The returned string is for debugging purpose and may change in any future SIS version.
     * The current implementation is like below:
     *
     * {@preformat text
     *     Attribute[“temperature” : Float] = {20.3, 17.8, 21.1}
     *     └─ characteristics: units=°C, accuracy=0.1
     * }
     *
     * @return a string representation of this attribute for debugging purpose.
     */
    @Override
    public String toString() {
        final StringBuilder buffer = FieldType.toString(isDeprecated(type), "Attribute", type.getName(),
                Classes.getShortName(type.getValueClass()), getValues().iterator());
        if (characteristics != null && !characteristics.isEmpty()) {
            buffer.append(System.lineSeparator());
            String separator = "└─ characteristics: ";
            for (final Map.Entry<String,AbstractAttribute<?>> entry : characteristics.entrySet()) {
                buffer.append(separator).append(entry.getKey()).append('=').append(entry.getValue().getValue());
                separator = ", ";
            }
        }
        return buffer.toString();
    }

    /**
     * Returns a copy of this attribute if cloning is supported.
     * The decision to support cloning or not is left to subclasses. If the subclass does not implement
     * the {@link Cloneable} interface, then this method throws a {@link CloneNotSupportedException}.
     * Otherwise the default implementation returns a <em>shallow</em> copy of this {@code Attribute}:
     * the attribute {@linkplain #getValue() value} and {@linkplain #characteristics() characteristics}
     * are <strong>not</strong> cloned.
     * However subclasses may choose to do otherwise.
     *
     * @return a clone of this attribute.
     * @throws CloneNotSupportedException if this attribute, the {@linkplain #getValue() value}
     *         or one of its {@linkplain #characteristics() characteristics} can not be cloned.
     */
    @Override
    @SuppressWarnings("unchecked")
    public AbstractAttribute<V> clone() throws CloneNotSupportedException {
        final AbstractAttribute<V> clone = (AbstractAttribute<V>) super.clone();
        final Map<String,AbstractAttribute<?>> c = clone.characteristics;
        if (c instanceof CharacteristicMap) {
            clone.characteristics = ((CharacteristicMap) c).clone();
        }
        return clone;
    }
}
