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

import java.net.URI;
import java.util.Set;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Collection;
import java.util.Collections;
import java.util.AbstractMap;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.io.Serializable;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.citation.Citation;
import org.apache.sis.xml.XLink;
import org.apache.sis.xml.IdentifierMap;
import org.apache.sis.xml.IdentifierSpace;
import org.apache.sis.internal.util.Strings;
import org.apache.sis.internal.util.SetOfUnknownSize;

import static org.apache.sis.util.collection.Containers.hashMapCapacity;


/**
 * Implementation of the map of identifiers associated to {@link org.apache.sis.xml.IdentifiedObject} instances.
 * This base class implements an unmodifiable map, but the {@link ModifiableIdentifierMap} subclass add write
 * capabilities.
 *
 * <p>This class works as a wrapper around a collection of identifiers. Because all operations
 * are performed by an iteration over the collection elements, this implementation is suitable
 * only for small maps (less than 10 elements). Given that objects typically have only one or
 * two identifiers, this is considered acceptable.</p>
 *
 * <h2>Special cases</h2>
 * The identifiers for the following authorities are handled in a special way:
 * <ul>
 *   <li>{@link IdentifierSpace#HREF}: handled as a shortcut to {@link XLink#getHRef()}.</li>
 * </ul>
 *
 * <h2>Handling of duplicated authorities</h2>
 * The collection shall not contain more than one identifier for the same
 * {@linkplain Identifier#getAuthority() authority}. However duplications may happen if the user
 * has direct access to the list, for example through {@link Citation#getIdentifiers()}. If such
 * duplication is found, then this map implementation applies the following rules:
 *
 * <ul>
 *   <li>All getter methods (including the iterators and the values returned by the {@code put}
 *       and {@code remove} methods) return only the identifier code associated to the first
 *       occurrence of each authority. Any subsequent occurrences of the same authorities are
 *       silently ignored.</li>
 *   <li>All setter methods <em>may</em> affect <em>all</em> identifiers previously associated to
 *       the given authority, not just the first occurrence. The only guarantee is that the list
 *       is update in such a way that the effect of setter methods are visible to subsequent calls
 *       to getter methods.</li>
 * </ul>
 *
 * <h2>Handling of null identifiers</h2>
 * The collection of identifiers shall not contain any null element. This is normally ensured by
 * the {@link org.apache.sis.metadata.ModifiableMetadata} internal collection implementations.
 * This class performs opportunist null checks as an additional safety, but consistency is not
 * guaranteed. See {@link #size()} for more information.
 *
 * <h2>Thread safety</h2>
 * This class is thread safe if the underlying identifier collection is thread safe.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.7
 *
 * @see org.apache.sis.xml.IdentifiedObject
 *
 * @since 0.3
 * @module
 */
public class IdentifierMapAdapter extends AbstractMap<Citation,String> implements IdentifierMap, Serializable {
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = -1445849218952061605L;

    /**
     * An immutable empty instance.
     */
    public static final IdentifierMap EMPTY = new IdentifierMapAdapter(Collections.emptySet());

    /**
     * The identifiers to wrap in a map view.
     */
    public final Collection<Identifier> identifiers;

    /**
     * Creates a new map which will be a view over the given identifiers.
     *
     * @param  identifiers  the identifiers to wrap in a map view.
     */
    public IdentifierMapAdapter(final Collection<Identifier> identifiers) {
        this.identifiers = identifiers;
    }

    /**
     * If the given authority is a special case, returns its {@link NonMarshalledAuthority} integer enum.
     * Otherwise returns -1. See javadoc for more information about special cases.
     *
     * @param  authority  a {@link Citation} constant. The type is relaxed to {@code Object}
     *         because the signature of some {@code Map} methods are that way.
     */
    static int specialCase(final Object authority) {
        if (authority == IdentifierSpace.HREF) return NonMarshalledAuthority.HREF;
        // A future Apache SIS version may add more special cases here.
        return -1;
    }

    /**
     * Extracts the {@code xlink:href} value from the {@link XLink} if presents.
     * This method does not test if an explicit {@code xlink:href} identifier exists;
     * this check must be done by the caller <strong>before</strong> to invoke this method.
     *
     * @see ModifiableIdentifierMap#setHRef(URI)
     */
    private URI getHRef() {
        final Identifier identifier = getIdentifier(IdentifierSpace.XLINK);
        if (identifier instanceof SpecializedIdentifier<?>) {
            final Object link = ((SpecializedIdentifier<?>) identifier).value;
            if (link instanceof XLink) {
                return ((XLink) link).getHRef();
            }
        }
        return null;
    }

    /**
     * Returns the string representation of the given value, or {@code null} if none.
     *
     * @param  value  the value returned be one of the above {@code getFoo()} methods.
     */
    private static String toString(final Object value) {
        return (value != null) ? value.toString() : null;
    }




    ////////////////////////////////////////////////////////////////////////////////////////
    ////////                                                                        ////////
    ////////    END OF SPECIAL CASES.                                               ////////
    ////////                                                                        ////////
    ////////    Implementation of IdentifierMap methods follow. Each method may     ////////
    ////////    have a switch statement over the special cases declared above.      ////////
    ////////                                                                        ////////
    ////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Whether this map support {@code put} and {@code remove} operations.
     */
    boolean isModifiable() {
        return false;
    }

    /**
     * Returns {@code true} if the collection of identifiers contains at least one element.
     * This method does not verify if the collection contains null element (it should not).
     */
    @Override
    public final boolean isEmpty() {
        return identifiers.isEmpty();
    }

    /**
     * Counts the number of entries, ignoring null elements and duplicated authorities.
     *
     * <p>Because {@code null} elements are ignored, this method may return 0 even if {@link #isEmpty()}
     * returns {@code false}. However this inconsistency should not happen in practice because
     * {@link org.apache.sis.metadata.ModifiableMetadata} internal collection implementations
     * do not allow null values.</p>
     */
    @Override
    public final int size() {
        final HashSet<Citation> done = new HashSet<>(hashMapCapacity(identifiers.size()));
        for (final Identifier identifier : identifiers) {
            if (identifier != null) {
                done.add(identifier.getAuthority());
            }
        }
        return done.size();
    }

    /**
     * Returns {@code true} if at least one identifier declares the given {@linkplain Identifier#getCode() code}.
     *
     * @param  code  the code to search, which should be an instance of {@link String}.
     * @return {@code true} if at least one identifier uses the given code.
     */
    @Override
    public final boolean containsValue(final Object code) {
        if (code instanceof String) {
            for (final Identifier identifier : identifiers) {
                if (identifier != null && code.equals(identifier.getCode())) {
                    return true;
                }
            }
            return code.equals(toString(getHRef()));
            // A future Apache SIS version may add more special cases here.
        }
        return false;
    }

    /**
     * Returns {@code true} if at least one identifier declares the given
     * {@linkplain Identifier#getAuthority() authority}.
     *
     * @param  authority  the authority to search, which should be an instance of {@link Citation}.
     * @return {@code true} if at least one identifier uses the given authority.
     */
    @Override
    public final boolean containsKey(final Object authority) {
        if (authority instanceof Citation) {
            if (getIdentifier((Citation) authority) != null) {
                return true;
            }
            switch (specialCase(authority)) {
                case NonMarshalledAuthority.HREF: return getHRef() != null;
                // A future Apache SIS version may add more special cases here.
            }
        }
        return false;
    }

    /**
     * Returns the identifier for the given key, or {@code null} if none.
     */
    final Identifier getIdentifier(final Citation authority) {
        for (final Identifier identifier : identifiers) {
            if (identifier != null && Objects.equals(authority, identifier.getAuthority())) {
                return identifier;
            }
        }
        return null;
    }

    /**
     * Returns the identifier associated with the given authority,
     * or {@code null} if no specialized identifier was found.
     */
    @Override
    @SuppressWarnings("unchecked")
    public final <T> T getSpecialized(final IdentifierSpace<T> authority) {
        final Identifier identifier = getIdentifier(authority);
        if (identifier instanceof SpecializedIdentifier<?>) {
            return ((SpecializedIdentifier<T>) identifier).value;
        }
        switch (specialCase(authority)) {
            case NonMarshalledAuthority.HREF: return (T) getHRef();
            // A future Apache SIS version may add more special cases here.
        }
        return null;
    }

    /**
     * Returns the code of the first identifier associated with the given
     * {@linkplain Identifier#getAuthority() authority}, or {@code null} if no identifier was found.
     *
     * @param  authority  the authority to search, which should be an instance of {@link Citation}.
     * @return the code of the identifier for the given authority, or {@code null} if none.
     */
    @Override
    public final String get(final Object authority) {
        if (authority instanceof Citation) {
            final Identifier identifier = getIdentifier((Citation) authority);
            if (identifier != null) {
                return identifier.getCode();
            }
            switch (specialCase(authority)) {
                case NonMarshalledAuthority.HREF: return toString(getHRef());
                // A future Apache SIS version may add more special cases here.
            }
        }
        return null;
    }

    /**
     * Removes all identifiers associated with the given {@linkplain Identifier#getAuthority() authority}.
     *
     * @param  authority  the authority to search, which should be an instance of {@link Citation}.
     * @return the code of the identifier for the given authority, or {@code null} if none.
     * @throws UnsupportedOperationException if the collection of identifiers is unmodifiable.
     */
    @Override
    public String remove(Object authority) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    /**
     * Removes every entries in the underlying collection.
     *
     * @throws UnsupportedOperationException if the collection of identifiers is unmodifiable.
     */
    @Override
    public void clear() throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    /**
     * Sets the code of the identifier having the given authority to the given value.
     * If no identifier is found for the given authority, a new one is created.
     * If more than one identifier is found for the given authority, then all previous identifiers may be removed
     * in order to ensure that the new entry will be the first entry, so it can be find by the {@code get} method.
     *
     * @param  authority  the authority for which to set the code.
     * @param  code  the new code for the given authority, or {@code null} for removing the entry.
     * @return the previous code for the given authority, or {@code null} if none.
     * @throws UnsupportedOperationException if the collection of identifiers is unmodifiable.
     */
    @Override
    public String put(Citation authority, String code) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    /**
     * Sets the identifier associated with the given authority, and returns the previous value.
     */
    @Override
    public <T> T putSpecialized(IdentifierSpace<T> authority, T value) throws UnsupportedOperationException {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns a view over the collection of identifiers. This view supports removal operation
     * if the underlying collection of identifiers supports the {@link Iterator#remove()} method.
     *
     * <p>If the backing identifier collection contains null entries, those entries will be ignored.
     * If the backing collection contains many entries for the same authority, then only the first
     * occurrence is included.</p>
     *
     * @return a view over the collection of identifiers.
     */
    @Override
    public Set<Entry<Citation,String>> entrySet() {
        /*
         * Do not cache the entries set because if is very cheap to create and not needed very often.
         * Not caching allows this implementation to be thread-safe without synchronization or volatile
         * fields if the underlying list is thread-safe. Furthermore, IdentifierMapAdapter are temporary
         * objects anyway in the current ISOMetadata implementation.
         */
        return new SetOfUnknownSize<Entry<Citation,String>>() {
            /** Delegates to the enclosing class. */
            @Override public void clear() throws UnsupportedOperationException {
                IdentifierMapAdapter.this.clear();
            }

            /** Delegates to the enclosing class. */
            @Override public boolean isEmpty() {
                return IdentifierMapAdapter.this.isEmpty();
            }

            /** Delegates to the enclosing class. */
            @Override public int size() {
                return IdentifierMapAdapter.this.size();
            }

            /** Returns an iterator over the (<var>citation</var>, <var>code</var>) entries. */
            @Override public Iterator<Entry<Citation, String>> iterator() {
                return new Iter(identifiers, isModifiable());
            }
        };
    }

    /**
     * The iterator over the (<var>citation</var>, <var>code</var>) entries. This iterator is created by the
     * {@link #entrySet()} collection. It extends {@link HashMap} as an opportunist implementation strategy,
     * but users do not need to know this detail.
     *
     * <p>This iterator supports the {@link #remove()} operation if the underlying collection supports it.</p>
     *
     * <p>The map entries are used as a safety against duplicated authority values. The map values
     * are non-null only after we iterated over an authority. Then the value is {@link Boolean#TRUE}
     * if the identifier has been removed, of {@code Boolean#FALSE} otherwise.</p>
     *
     * @author  Martin Desruisseaux (Geomatys)
     * @version 0.7
     * @since   0.3
     * @module
     */
    @SuppressWarnings("serial")                 // Not intended to be serialized.
    private static final class Iter extends HashMap<Citation,Boolean> implements Iterator<Entry<Citation,String>> {
        /**
         * An iterator over the {@link IdentifierMapAdapter#identifiers} collection,
         * or (@code null} if we have reached the iteration end.
         */
        private Iterator<? extends Identifier> identifiers;

        /**
         * The next entry to be returned by {@link #next()}, or {@code null} if not yet computed.
         * This field will be computed only when {@link #next()} or {@link #hasNext()} is invoked.
         */
        private transient Entry<Citation,String> next;

        /**
         * The current authority. Used only for removal operations.
         */
        private transient Citation authority;

        /**
         * {@code true} if the iterator should support the {@link #remove()} operation.
         */
        private final boolean isModifiable;

        /**
         * Creates a new iterator for the given collection of identifiers.
         */
        Iter(final Collection<? extends Identifier> identifiers, final boolean isModifiable) {
            super(hashMapCapacity(identifiers.size()));
            this.identifiers = identifiers.iterator();
            this.isModifiable = isModifiable;
        }

        /**
         * Advances to the next non-null identifier, skips duplicated authorities, wraps the
         * identifier in an entry if needed and stores the result in the {@link #next} field.
         * If we reach the iteration end, then this method set the {@link #identifiers}
         * iterator to {@code null}.
         */
        private void toNext() {
            final Iterator<? extends Identifier> it = identifiers;
            if (it != null) {
                while (it.hasNext()) {
                    final Identifier identifier = it.next();
                    if (identifier != null) {
                        final Citation authority = identifier.getAuthority();
                        final Boolean state = put(authority, Boolean.FALSE);
                        if (state == null) {
                            if (identifier instanceof IdentifierMapEntry) {
                                next = (IdentifierMapEntry) identifier;
                            } else {
                                next = new IdentifierMapEntry.Immutable(authority, identifier.getCode());
                            }
                            this.authority = authority;
                            return;
                        }
                        if (state) {
                            // Found a duplicated entry, and user asked for the
                            // removal of that authority.
                            it.remove();
                        }
                    }
                }
                identifiers = null;
            }
        }

        /**
         * If we need to search for the next element, fetches it now.
         * Then returns {@code true} if we didn't reached the iteration end.
         */
        @Override
        public boolean hasNext() {
            if (next == null) {
                toNext();
            }
            return identifiers != null;
        }

        /**
         * If we need to search for the next element, searches it now. Then set {@link #next}
         * to {@code null} as a flag meaning that next invocations will need to search again
         * for an element, and returns the element that we got.
         */
        @Override
        public Entry<Citation,String> next() throws NoSuchElementException {
            Entry<Citation,String> entry = next;
            if (entry == null) {
                toNext();
                entry = next;
            }
            next = null;
            if (identifiers == null) {
                throw new NoSuchElementException();
            }
            return entry;
        }

        /**
         * Removes the last element returned by {@link #next()}. Note that if the {@link #next}
         * field is non-null, that would mean that the iteration has moved since the last call
         * to the {@link #next()} method, in which case the iterator is invalid.
         */
        @Override
        public void remove() throws IllegalStateException {
            if (!isModifiable) {
                throw new UnsupportedOperationException();
            }
            final Iterator<? extends Identifier> it = identifiers;
            if (it == null || next != null) {
                throw new IllegalStateException();
            }
            it.remove();
            put(authority, Boolean.TRUE);
        }

        /**
         * Iterators are not intended to be cloned.
         */
        @Override
        @SuppressWarnings("CloneDoesntCallSuperClone")
        public Object clone() {
            throw new UnsupportedOperationException();
        }

        /**
         * Returns the next value to be returned, for debugging purpose only.
         */
        @Override
        public String toString() {
            return Strings.toString(Iter.class, "next", next);
        }
    }

    /**
     * Overrides the string representation in order to use only the authority title as keys.
     * We do that because the string representations of {@code DefaultCitation} objects are
     * very big.
     *
     * <p>String examples:</p>
     * <ul>
     *   <li>{gml:id=“myID”}</li>
     *   <li>{gco:uuid=“42924124-032a-4dfe-b06e-113e3cb81cf0”}</li>
     *   <li>{xlink:href=“http://www.mydomain.org/myHREF”}</li>
     * </ul>
     *
     * @see SpecializedIdentifier#toString()
     */
    @Override
    public String toString() {
    final StringBuilder buffer = new StringBuilder(50).append('{');
    for (final Entry<Citation,String> entry : entrySet()) {
        if (buffer.length() != 1) {
                buffer.append(", ");
            }
            SpecializedIdentifier.format(buffer, entry.getKey(), entry.getValue());
        }
        return buffer.append('}').toString();
    }
}
