/*
 * 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 org.opengis.util.GenericName;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.internal.util.Cloner;
import org.apache.sis.internal.util.AbstractMap;
import org.apache.sis.internal.util.AbstractMapEntry;
import org.apache.sis.internal.feature.Resources;

// Branch-dependent imports
import org.opengis.feature.Attribute;
import org.opengis.feature.AttributeType;
import org.opengis.feature.InvalidPropertyValueException;
import org.opengis.feature.PropertyNotFoundException;


/**
 * Implementation of {@link AbstractAttribute#characteristics()} map.
 * This map holds only the attribute characteristics which have been explicitly set or requested.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.6
 * @since   0.5
 * @module
 */
final class CharacteristicMap extends AbstractMap<String,Attribute<?>> implements Cloneable {
    /**
     * The attribute source for which to provide characteristics.
     */
    private final Attribute<?> source;

    /**
     * Characteristics of the {@code source} attribute, created when first needed.
     */
    Attribute<?>[] characterizedBy;

    /**
     * Description of the attribute characteristics.
     */
    final CharacteristicTypeMap types;

    /**
     * Creates an initially empty map of attribute characteristics.
     *
     * @param  source  the attribute which is characterized by {@code characterizedBy}.
     * @param  types   description of the characteristics of {@code source}.
     */
    CharacteristicMap(final Attribute<?> source, final CharacteristicTypeMap types) {
        this.source = source;
        this.types  = types;
    }

    /**
     * Returns a copy of this map. Characteristics are also cloned.
     *
     * @return a copy of this map.
     */
    @Override
    public CharacteristicMap clone() throws CloneNotSupportedException {
        final CharacteristicMap clone = (CharacteristicMap) super.clone();
        Attribute<?>[] c = clone.characterizedBy;
        if (c != null) {
            clone.characterizedBy = c = c.clone();
            final Cloner cloner = new Cloner();
            for (int i=0; i<c.length; i++) {
                final Attribute<?> attribute = c[i];
                if (attribute instanceof Cloneable) {
                    c[i] = (Attribute<?>) cloner.clone(attribute);
                }
            }
        }
        return clone;
    }

    /**
     * Removes all entries in this map.
     */
    @Override
    public void clear() {
        /*
         * Implementation note: We could keep existing array and clear it with Arrays.fill(characterizedBy, null)
         * instead, but maybe the user does not plan to store characteristics anymore for the attribute. Setting
         * the array reference to null free more memory in such cases.
         */
        characterizedBy = null;
    }

    /**
     * Returns {@code false} if this map contains at least one characteristic.
     */
    @Override
    public boolean isEmpty() {
        if (characterizedBy != null) {
            for (final Attribute<?> attribute : characterizedBy) {
                if (attribute != null) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Returns the number of attribute characteristics.
     */
    @Override
    public int size() {
        int n = 0;
        if (characterizedBy != null) {
            for (final Attribute<?> attribute : characterizedBy) {
                if (attribute != null) {
                    n++;
                }
            }
        }
        return n;
    }

    /**
     * Returns the attribute characteristic for the given name, or {@code null} if none.
     */
    @Override
    public Attribute<?> get(final Object key) {
        if (characterizedBy != null) {
            final Integer index = types.indices.get(key);
            if (index != null) {
                return characterizedBy[index];
            }
        }
        return null;
    }

    /**
     * Removes the attribute characteristic for the given name.
     */
    @Override
    public Attribute<?> remove(final Object key) {
        if (characterizedBy != null) {
            final Integer index = types.indices.get(key);
            if (index != null) {
                final Attribute<?> previous = characterizedBy[index];
                characterizedBy[index] = null;
                return previous;
            }
        }
        return null;
    }

    /**
     * Returns the index for the characteristic of the given name.
     *
     * @param  key  the name for which to get the characteristic index.
     * @return the index for the characteristic of the given name.
     * @throws PropertyNotFoundException if the given key is not the name of a characteristic in this map.
     */
    private int indexOf(final String key) {
        ArgumentChecks.ensureNonNull("key", key);
        final Integer index = types.indices.get(key);
        if (index == null) {
            throw new PropertyNotFoundException(Resources.format(
                    Resources.Keys.CharacteristicsNotFound_2, source.getName(), key));
        }
        return index;
    }

    /**
     * Ensures that the given attribute type is the instance that we expect at the given index.
     * If the given instance is not the expected one, then an {@link IllegalArgumentException}
     * will be thrown with an error message formatted using the name of expected and given types.
     *
     * @param  index  index of the expected attribute type.
     * @param  type   the actual attribute type.
     */
    final void verifyAttributeType(final int index, final AttributeType<?> type) {
        final AttributeType<?> expected = types.characterizedBy[index];
        if (!expected.equals(type)) {
            final GenericName en = expected.getName();
            final GenericName an = type.getName();
            throw new InvalidPropertyValueException(String.valueOf(en).equals(String.valueOf(an))
                    ? Resources.format(Resources.Keys.MismatchedPropertyType_1, en)
                    : Resources.format(Resources.Keys.CanNotSetCharacteristics_2, en.push(source.getName()), an));
        }
    }

    /**
     * Sets the attribute characteristic for the given name.
     *
     * @param  key  the name of the characteristic to set.
     * @throws IllegalArgumentException if the given key is not the name of a characteristic in this map.
     */
    @Override
    public Attribute<?> put(final String key, final Attribute<?> value) {
        final int index = indexOf(key);
        ArgumentChecks.ensureNonNull("value", value);
        verifyAttributeType(index, value.getType());
        if (characterizedBy == null) {
            characterizedBy = new Attribute<?>[types.characterizedBy.length];
        }
        final Attribute<?> previous = characterizedBy[index];
        characterizedBy[index] = value;
        return previous;
    }

    /**
     * If no characteristic exists for the given name and that name is valid,
     * creates a new map entry with a default {@code Attribute} characteristic.
     *
     * @param  name  the name of the characteristic to create, if it does not already exist.
     * @return {@code true} if a new characteristic has been created for the given name.
     * @throws IllegalArgumentException if the given key is not the name of a characteristic in this map.
     */
    @Override
    protected boolean addKey(final String name) {
        final int index = indexOf(name);
        if (characterizedBy == null) {
            characterizedBy = new Attribute<?>[types.characterizedBy.length];
        }
        if (characterizedBy[index] == null) {
            characterizedBy[index] = types.characterizedBy[index].newInstance();
            return true;
        }
        return false;
    }

    /**
     * Adds the given characteristic if none is currently associated for the same characteristic name.
     *
     * @param  value  the characteristic to add.
     * @return {@code true} if the characteristic has been added.
     * @throws IllegalArgumentException if given characteristic is not valid for this map.
     * @throws IllegalStateException if another characteristic already exists for the characteristic name.
     */
    @Override
    protected boolean addValue(final Attribute<?> value) {
        ArgumentChecks.ensureNonNull("value", value);
        final int index = indexOf(value.getName().toString());
        verifyAttributeType(index, value.getType());
        if (characterizedBy == null) {
            characterizedBy = new Attribute<?>[types.characterizedBy.length];
        }
        final Attribute<?> previous = characterizedBy[index];
        if (previous == null) {
            characterizedBy[index] = value;
            return true;
        } else if (previous.equals(value)) {
            return false;
        } else {
            throw new IllegalStateException(Resources.format(
                    Resources.Keys.CharacteristicsAlreadyExists_2, source.getName(), value.getName()));
        }
    }

    /**
     * Returns an iterator over the entries.
     */
    @Override
    protected EntryIterator<String, Attribute<?>> entryIterator() {
        if (characterizedBy == null) {
            return null;
        }
        return new EntryIterator<String, Attribute<?>>() {
            /** Index of the current element to return in the iteration. */
            private int index = -1;

            /** The element to return, or {@code null} if we reached the end of iteration. */
            private Attribute<?> value;

            /** Returns {@code true} if there is more entries in the iteration. */
            @Override protected boolean next() {
                while (++index < characterizedBy.length) {
                    value = characterizedBy[index];
                    if (value != null) return true;
                }
                value = null;
                return false;
            }

            /** Returns the name of the attribute characteristic. */
            @Override protected String getKey() {
                return value.getType().getName().toString();
            }

            /** Returns the attribute characteristic (never {@code null}). */
            @Override protected Attribute<?> getValue() {
                return value;
            }

            /** Creates and return the next entry. */
            @Override protected Map.Entry<String, Attribute<?>> getEntry() {
                return new Entry(index, value);
            }

            /** Removes the last element returned by {@link #next()}. */
            @Override protected void remove() {
                characterizedBy[index] = null;
            }
        };
    }

    /**
     * An entry returned by the {@link CharacteristicMap#entrySet()} iterator.
     * The key and value are never null, even in case of concurrent modification.
     * This entry supports the {@link #setValue(Attribute)} operation.
     */
    private final class Entry extends AbstractMapEntry<String, Attribute<?>> {
        /** Index of the attribute characteristics represented by this entry. */
        private final int index;

        /** The current attribute value, which is guaranteed to be non-null. */
        private Attribute<?> value;

        /** Creates a new entry for the characteristic at the given index. */
        Entry(final int index, final Attribute<?> value) {
            this.index = index;
            this.value = value;
        }

        /** Returns the name of the attribute characteristic. */
        @Override public String getKey() {
            return value.getType().getName().toString();
        }

        /** Returns the attribute characteristic (never {@code null}). */
        @Override public Attribute<?> getValue() {
            return value;
        }

        /** Sets the attribute characteristic. */
        @Override public Attribute<?> setValue(final Attribute<?> value) {
            ArgumentChecks.ensureNonNull("value", value);
            verifyAttributeType(index, value.getType());
            final Attribute<?> previous = this.value;
            characterizedBy[index] = value;
            this.value = value;
            return previous;
        }
    }
}
