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

import java.util.Locale;
import java.util.Iterator;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.citation.Citation;
import org.opengis.referencing.ReferenceIdentifier;
import org.opengis.util.InternationalString;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Characters;
import org.apache.sis.util.Deprecable;
import org.apache.sis.util.Static;


/**
 * Methods working on {@link Identifier} instances.
 *
 * @author Martin Desruisseaux (Geomatys)
 * @since   1.0
 * @version 1.0
 * @module
 */
public final class Identifiers extends Static {
    /**
     * Do not allow instantiation of this class.
     */
    private Identifiers() {
    }

    /**
     * Returns {@code true} if the given code is {@code "EPSG"} while the codespace is {@code "IOGP"} or {@code "OGP"}
     * (ignoring case). This particular combination of code and codespace is handled in a special way.
     *
     * <p>This method can be used for identifying where in Apache SIS source code the relationship between
     * EPSG authority and IOGP code space is hard-coded.</p>
     *
     * @param  codeSpace  the identifier code space, or {@code null}.
     * @param  code       the identifier code, or {@code null}.
     * @return {@code true} if the given identifier is {@code "IOGP:EPSG"}.
     *
     * @see org.apache.sis.metadata.iso.citation.Citations#EPSG
     */
    public static boolean isEPSG(final String codeSpace, final String code) {
        return Constants.EPSG.equalsIgnoreCase(code) &&
              (Constants.IOGP.equalsIgnoreCase(codeSpace) || "OGP".equalsIgnoreCase(codeSpace) ||
               Constants.EPSG.equalsIgnoreCase(codeSpace));
        // "OGP" is a legacy abbreviation that existed before "IOGP".
    }

    /**
     * Return {@code true} if the given object is deprecated.
     */
    private static boolean isDeprecated(final Object object) {
        return (object instanceof Deprecable) && ((Deprecable) object).isDeprecated();
    }

    /**
     * Returns a "unlocalized" string representation of the given international string, or {@code null} if none
     * or if the string is deprecated. This method is used by {@link #getIdentifier(Citation, boolean)}, which
     * is why we don't want the localized string.
     */
    private static String toString(final InternationalString title) {
        return (title != null && !isDeprecated(title))
               ? CharSequences.trimWhitespaces(title.toString(Locale.ROOT)) : null;
    }

    /**
     * Infers an identifier from the given citation, or returns {@code null} if no identifier has been found.
     * This method removes leading and trailing {@linkplain Character#isWhitespace(int) whitespaces}.
     * See {@link Citations#getIdentifier(Citation)} for the public documentation of this method.
     *
     * <p><b>Which method to use:</b></p>
     * <ul>
     *   <li>For information purpose (e.g. some {@code toString()} methods), use {@code getIdentifier(…, false)}.</li>
     *   <li>For WKT formatting, use {@code getIdentifier(…, true)} in order to preserve formatting characters.</li>
     *   <li>For assigning a value to a {@code codeSpace} field, use {@link Citations#toCodeSpace(Citation)}.</li>
     * </ul>
     *
     * Use {@code toCodeSpace(…)} method when assigning values to be returned by methods like
     * {@link ReferenceIdentifier#getCodeSpace()}, since those values are likely to be compared without special
     * care about ignorable identifier characters. But if the intent is to format a more complex string
     * like WKT or {@code toString()}, then we suggest to use {@code getIdentifier(citation, true)} instead,
     * which will produce the same result but preserving the ignorable characters, which can be useful
     * for formatting purpose.
     *
     * @param  citation  the citation for which to get the identifier, or {@code null}.
     * @param  strict    {@code true} for returning a non-null value only if the identifier is a valid Unicode identifier.
     * @return a non-empty identifier for the given citation without leading or trailing whitespaces,
     *         or {@code null} if the given citation is null or does not declare any identifier or title.
     *
     * @see <a href="https://issues.apache.org/jira/browse/SIS-201">SIS-201</a>
     */
    public static String getIdentifier(final Citation citation, final boolean strict) {
        if (citation != null) {
            boolean isUnicode = false;      // Whether 'identifier' is a Unicode identifier.
            String identifier = null;       // The best identifier found so far.
            String codeSpace  = null;       // Code space of the identifier, or null if none.
            final Iterator<? extends Identifier> it = CollectionsExt.nonEmptyIterator(citation.getIdentifiers());
            if (it != null) while (it.hasNext()) {
                final Identifier id = it.next();
                if (id != null && !isDeprecated(id)) {
                    final String candidate = CharSequences.trimWhitespaces(id.getCode());
                    if (candidate != null && !candidate.isEmpty()) {
                        /*
                         * For a non-empty identifier, verify if both the code and its codespace are valid
                         * Unicode identifiers. If a codespace exists, then the code does not need to begin
                         * with a "Unicode identifier start" (it may be a "Unicode identifier part").
                         */
                        String cs = null;
                        if (id instanceof ReferenceIdentifier) {
                            cs = CharSequences.trimWhitespaces(((ReferenceIdentifier) id).getCodeSpace());
                        }
                        if (cs == null || cs.isEmpty()) {
                            cs = null;
                            isUnicode = CharSequences.isUnicodeIdentifier(candidate);
                        } else {
                            isUnicode = CharSequences.isUnicodeIdentifier(cs);
                            if (isUnicode) for (int i = 0; i < candidate.length();) {
                                final int c = candidate.codePointAt(i);
                                if (!Character.isUnicodeIdentifierPart(c) &&
                                        (strict || (c != '.' && c != '-')))
                                {
                                    /*
                                     * Above special case for '.' and '-' characters is documented
                                     * in the public Citations.getIdentifier(Citation) method.
                                     */
                                    isUnicode = false;
                                    break;
                                }
                                i += Character.charCount(c);
                            }
                        }
                        /*
                         * If we found a Unicode identifier, we are done and we can exit the loop.
                         * Otherwise retain the first identifier and continue the search for Unicode identifier.
                         */
                        if (identifier == null || isUnicode) {
                            identifier = candidate;
                            codeSpace  = cs;
                            if (isUnicode) break;
                        }
                    }
                }
            }
            /*
             * If no identifier has been found, fallback on the first title or alternate title.
             * We search for alternate titles because ISO specification said that those titles
             * are often used for abbreviations. Again we give preference to Unicode identifiers,
             * which are typically alternate titles.
             */
            if (identifier == null) {
                identifier = toString(citation.getTitle());     // Whitepaces removed by toString(…).
                if (identifier != null) {
                    if (identifier.isEmpty()) {
                        identifier = null;
                    } else {
                        isUnicode = CharSequences.isUnicodeIdentifier(identifier);
                    }
                }
                if (!isUnicode) {
                    final Iterator<? extends InternationalString> iterator = CollectionsExt.nonEmptyIterator(citation.getAlternateTitles());
                    if (iterator != null) while (iterator.hasNext()) {
                        final String candidate = toString(iterator.next());
                        if (candidate != null && !candidate.isEmpty()) {
                            isUnicode = CharSequences.isUnicodeIdentifier(candidate);
                            if (identifier == null || isUnicode) {
                                identifier = candidate;
                                if (isUnicode) break;
                            }
                        }
                    }
                }
            }
            /*
             * Finished searching in the identifiers, title and alternate titles. If the identifier that
             * we found is not a valid Unicode identifier, we will return it only if the caller did not
             * asked for strictly valid Unicode identifier.
             */
            if (isUnicode || !strict) {
                if (codeSpace != null && !isEPSG(codeSpace, identifier)) {
                    return codeSpace + (strict ? '_' : Constants.DEFAULT_SEPARATOR) + identifier;
                } else {
                    return identifier;
                }
            }
        }
        return null;
    }

    /**
     * Returns {@code true} if the given identifier authority matches the given {@code authority}.
     * If one of the authority is null, then the comparison fallback on the given {@code codeSpace}.
     * If the code spaces are also null, then this method conservatively returns {@code false}.
     *
     * @param  identifier  the identifier to compare.
     * @param  authority   the desired authority, or {@code null}.
     * @param  codeSpace   the desired code space or {@code null}, used as a fallback if an authority is null.
     * @return {@code true} if the authority or code space (as a fallback only) matches.
     */
    private static boolean authorityMatches(final Identifier identifier, final Citation authority, final String codeSpace) {
        if (authority != null) {
            final Citation other = identifier.getAuthority();
            if (other != null) {
                return Citations.identifierMatches(authority, other);
            }
        }
        if (codeSpace != null && identifier instanceof ReferenceIdentifier) {
            final String other = ((ReferenceIdentifier) identifier).getCodeSpace();
            if (other != null) {
                return CharSequences.equalsFiltered(codeSpace, other, Characters.Filter.UNICODE_IDENTIFIER, true);
            }
        }
        return false;
    }

    /**
     * Determines whether a match or mismatch is found between the two given collections of identifiers.
     * If any of the given collections is {@code null} or empty, then this method returns {@code null}.
     *
     * <p>According ISO 19162 (<cite>Well known text representation of coordinate reference systems</cite>),
     * {@linkplain org.apache.sis.referencing.AbstractIdentifiedObject#getIdentifiers() identifiers} should have precedence over
     * {@linkplain org.apache.sis.referencing.AbstractIdentifiedObject#getName() name} for identifying {@code IdentifiedObject}s,
     * at least in the case of {@linkplain org.apache.sis.referencing.operation.DefaultOperationMethod operation methods} and
     * {@linkplain org.apache.sis.parameter.AbstractParameterDescriptor parameters}.</p>
     *
     * @param  id1  the first collection of identifiers, or {@code null}.
     * @param  id2  the second collection of identifiers, or {@code null}.
     * @return {@code TRUE} or {@code FALSE} on match or mismatch respectively, or {@code null} if this method
     *         can not determine if there is a match or mismatch.
     */
    public static Boolean hasCommonIdentifier(final Iterable<? extends ReferenceIdentifier> id1,
                                              final Iterable<? extends ReferenceIdentifier> id2)
    {
        if (id1 != null && id2 != null) {
            boolean hasFound = false;
            for (final ReferenceIdentifier identifier : id1) {
                final Citation authority = identifier.getAuthority();
                final String   codeSpace = identifier.getCodeSpace();
                for (final Identifier other : id2) {
                    if (authorityMatches(identifier, authority, codeSpace)) {
                        if (CharSequences.equalsFiltered(identifier.getCode(), other.getCode(), Characters.Filter.UNICODE_IDENTIFIER, true)) {
                            return Boolean.TRUE;
                        }
                        hasFound = true;
                    }
                }
            }
            if (hasFound) {
                return Boolean.FALSE;
            }
        }
        return null;
    }
}
