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

import java.util.Collection;
import java.util.function.Predicate;
import javax.measure.Unit;
import org.opengis.util.CodeList;
import org.opengis.util.GenericName;
import org.opengis.referencing.datum.VerticalDatumType;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.cs.AxisDirection;
import org.apache.sis.util.StringBuilders;
import org.apache.sis.measure.Units;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Characters;


/**
 * Extensions to the standard set of {@link VerticalDatumType}.
 * Those constants are not in public API because they were intentionally omitted from ISO 19111,
 * and the ISO experts said that they should really not be public.
 *
 * <p>This class implements {@link Predicate} for opportunist reasons.
 * This implementation convenience may change in any future SIS version.</p>
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 1.0
 * @since   0.4
 * @module
 */
public final class VerticalDatumTypes implements Predicate<CodeList<?>> {
    /**
     * A vertical datum for ellipsoidal heights that are measured along the
     * normal to the ellipsoid used in the definition of horizontal datum.
     *
     * <p>Identifier: {@code CS_DatumType.CS_VD_Ellipsoidal}</p>
     */
    public static final VerticalDatumType ELLIPSOIDAL = VerticalDatumType.valueOf("ELLIPSOIDAL");

    /**
     * A vertical datum for orthometric heights that are measured along the plumb line.
     *
     * <p>Identifier: {@code CS_DatumType.CS_VD_Orthometric}</p>
     */
    public static final VerticalDatumType ORTHOMETRIC = VerticalDatumType.valueOf("ORTHOMETRIC");

    /**
     * Mapping from the numeric values used in legacy specification (OGC 01-009) to {@link VerticalDatumType}.
     * Indices in this array are the legacy codes minus 2000.
     *
     * <strong>This array shall not be fill before the above static constants.</strong>
     */
    private static final VerticalDatumType[] TYPES;

    /**
     * Mapping from {@link VerticalDatumType} to the numeric values used in legacy specification (OGC 01-009).
     */
    private static final short[] LEGACY_CODES;
    static {
        TYPES = new VerticalDatumType[7];
        LEGACY_CODES = new short[Math.max(ELLIPSOIDAL.ordinal(), ORTHOMETRIC.ordinal()) + 1];
        for (short code = 2000; code <= 2006; code++) {
            final VerticalDatumType type;
            switch (code) {
                case 2000: type = VerticalDatumType .OTHER_SURFACE; break;  // CS_VD_Other
                case 2001: type = VerticalDatumTypes.ORTHOMETRIC;   break;  // CS_VD_Orthometric
                case 2002: type = VerticalDatumTypes.ELLIPSOIDAL;   break;  // CS_VD_Ellipsoidal
                case 2003: type = VerticalDatumType .BAROMETRIC;    break;  // CS_VD_AltitudeBarometric
                case 2005: type = VerticalDatumType .GEOIDAL;       break;  // CS_VD_GeoidModelDerived
                case 2006: type = VerticalDatumType .DEPTH;         break;  // CS_VD_Depth
                default:   continue;
            }
            TYPES[code - 2000] = type;
            LEGACY_CODES[type.ordinal()] = code;
        }
    }

    /**
     * Returns the vertical datum type from a legacy code. The legacy codes were defined in
     * <a href="http://www.opengeospatial.org/standards/ct">OGC 01-009</a>
     * (<cite>Coordinate Transformation Services)</cite>, which also defined the version 1 of
     * <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html"><cite>Well
     * Known Text</cite></a> format (WKT 1). This method is used for WKT 1 parsing.
     *
     * @param  code  the legacy vertical datum code.
     * @return the vertical datum type, or {@code null} if the code is unrecognized.
     */
    public static VerticalDatumType fromLegacy(int code) {
        code -= 2000;
        return (code >= 0 && code < TYPES.length) ? TYPES[code] : null;
    }

    /**
     * Returns the legacy code for the datum type, or 0 if unknown.
     * This method is used for WKT 1 formatting.
     *
     * @param  type  the vertical datum type, or {@code null} if unknown.
     * @return the legacy code for the given datum type, or 0 if unknown.
     */
    public static int toLegacy(final VerticalDatumType type) {
        if (type != null) {
            final int ordinal = type.ordinal();
            if (ordinal >= 0 && ordinal < LEGACY_CODES.length) {
                return LEGACY_CODES[ordinal];
            }
        }
        return 0;
    }

    /**
     * Guesses the type of a datum from its name, aliases or a given vertical axis. This is sometime needed
     * after XML unmarshalling or WKT parsing, since GML 3.2 and ISO 19162 do not contain any attribute for
     * the datum type.
     *
     * <p>This method uses heuristic rules and may be changed in any future SIS version.
     * If the type can not be determined, defaults to {@link VerticalDatumType#OTHER_SURFACE}.</p>
     *
     * @param  name     the name of the datum for which to guess a type, or {@code null} if unknown.
     * @param  aliases  the aliases of the datum for which to guess a type, or {@code null} if unknown.
     * @param  axis     the vertical axis for which to guess a type, or {@code null} if unknown.
     * @return a datum type, or {@link VerticalDatumType#OTHER_SURFACE} if none can be guessed.
     */
    public static VerticalDatumType guess(final String name, final Collection<? extends GenericName> aliases,
            final CoordinateSystemAxis axis)
    {
        VerticalDatumType type = guess(name);
        if (type != null) {
            return type;
        }
        if (aliases != null) {
            for (final GenericName alias : aliases) {
                type = guess(alias.tip().toString());
                if (type != null) {
                    return type;
                }
            }
        }
        if (axis != null) {
            final Unit<?> unit = axis.getUnit();
            if (Units.isLinear(unit)) {
                final String abbreviation = axis.getAbbreviation();
                if (abbreviation.length() == 1) {
                    AxisDirection dir = AxisDirection.UP;               // Expected direction for accepting the type.
                    switch (abbreviation.charAt(0)) {
                        case 'h': type = ELLIPSOIDAL; break;
                        case 'H': type = VerticalDatumType.GEOIDAL; break;
                        case 'D': type = VerticalDatumType.DEPTH; dir = AxisDirection.DOWN; break;
                        default:  return VerticalDatumType.OTHER_SURFACE;
                    }
                    if (dir.equals(axis.getDirection())) {
                        return type;
                    }
                }
            } else if (Units.isPressure(unit)) {
                return VerticalDatumType.BAROMETRIC;
            }
        }
        return VerticalDatumType.OTHER_SURFACE;
    }

    /**
     * Guesses the type of a datum of the given name. This method attempts to guess only if the given name
     * contains at least one letter. If the type can not be determined, returns {@code null}.
     *
     * @param  name  name of the datum for which to guess a type, or {@code null}.
     * @return a datum type, or {@code null} if none can be guessed.
     */
    private static VerticalDatumType guess(final String name) {
        if (name != null) {
            if (CharSequences.equalsFiltered("Mean Sea Level", name, Characters.Filter.LETTERS_AND_DIGITS, true)) {
                return VerticalDatumType.GEOIDAL;
            }
            for (int i=0; i<name.length();) {
                final int c = name.codePointAt(i);
                if (Character.isLetter(c)) {
                    return CodeList.valueOf(VerticalDatumType.class, new VerticalDatumTypes(name), null);
                }
                i += Character.charCount(c);
            }
        }
        return null;
    }

    /**
     * The name of a datum to compare against the list of datum types,
     * in upper-case and (if possible) using US-ASCII characters.
     */
    private final StringBuilder datum;

    /**
     * Creates a new {@code CodeList.Filter} which will compare the given datum name against the list of datum types.
     * The comparison is case-insensitive and ignores some non-ASCII characters. The exact algorithm applied here is
     * implementation dependent and may change in any future version.
     *
     * @param  name  the datum name.
     */
    private VerticalDatumTypes(final String name) {
        final int length = name.length();
        datum = new StringBuilder(length);
        for (int i=0; i<length;) {
            final int c = name.codePointAt(i);
            datum.appendCodePoint(Character.toUpperCase(c));
            i += Character.charCount(c);
        }
        StringBuilders.toASCII(datum);
    }

    /**
     * Returns {@code true} if the name of the given code is the prefix of a word in the datum name.
     * We do not test the characters following the prefix because the word may be incomplete
     * (e.g. {@code "geoid"} versus {@code "geoidal"}).
     *
     * <p>This method is public as an implementation side-effect and should be ignored.</p>
     *
     * @param  code  the code to test.
     * @return {@code true} if the code matches the criterion.
      */
    @Override
    public boolean test(final CodeList<?> code) {
        final int i = datum.indexOf(code.name());
        return (i == 0) || (i >= 0 && Character.isWhitespace(datum.codePointBefore(i)));
    }
}
