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

import java.util.AbstractMap;
import java.io.IOException;
import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.channels.ReadableByteChannel;
import javax.xml.bind.annotation.XmlTransient;
import javax.measure.quantity.Angle;
import org.opengis.util.FactoryException;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.ParameterNotFoundException;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.referencing.operation.Transformation;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.apache.sis.referencing.operation.transform.InterpolatedTransform;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.parameter.Parameters;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.collection.Cache;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.internal.system.DataDirectory;
import org.apache.sis.measure.Units;


/**
 * The provider for <cite>"North American Datum Conversion"</cite> (EPSG:9613).
 * This transform requires data that are not bundled by default with Apache SIS.
 *
 * <p>The files given in parameters are theoretically binary files. However this provider accepts also ASCII files.
 * Those two kinds of files are recognized automatically; there is no need to specify whether the files are ASCII
 * or binary.</p>
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @author  Rueben Schulz (UBC)
 * @version 0.8
 *
 * @see <a href="http://www.ngs.noaa.gov/cgi-bin/nadcon.prl">NADCON on-line computation</a>
 *
 * @since 0.7
 * @module
 */
@XmlTransient
public final class NADCON extends AbstractProvider {
    /**
     * Serial number for inter-operability with different versions.
     */
    private static final long serialVersionUID = -4707304160205218546L;

    /**
     * The operation parameter descriptor for the <cite>"Latitude difference file"</cite> parameter value.
     * The default value is {@code "conus.las"}.
     *
     * <!-- Generated by ParameterNameTableGenerator -->
     * <table class="sis">
     *   <caption>Parameter names</caption>
     *   <tr><td> EPSG:    </td><td> Latitude difference file </td></tr>
     * </table>
     * <b>Notes:</b>
     * <ul>
     *   <li>Default value: {@code conus.las}</li>
     * </ul>
     */
    private static final ParameterDescriptor<Path> LATITUDE;

    /**
     * The operation parameter descriptor for the <cite>"Longitude difference file"</cite> parameter value.
     * The default value is {@code "conus.los"}.
     *
     * <!-- Generated by ParameterNameTableGenerator -->
     * <table class="sis">
     *   <caption>Parameter names</caption>
     *   <tr><td> EPSG:    </td><td> Longitude difference file </td></tr>
     * </table>
     * <b>Notes:</b>
     * <ul>
     *   <li>Default value: {@code conus.los}</li>
     * </ul>
     */
    private static final ParameterDescriptor<Path> LONGITUDE;

    /**
     * The group of all parameters expected by this coordinate operation.
     */
    public static final ParameterDescriptorGroup PARAMETERS;
    static {
        final ParameterBuilder builder = builder();
        LATITUDE = builder
                .addIdentifier("8657")
                .addName("Latitude difference file")
                .create(Path.class, Paths.get("conus.las"));
        LONGITUDE = builder
                .addIdentifier("8658")
                .addName("Longitude difference file")
                .create(Path.class, Paths.get("conus.los"));
        PARAMETERS = builder
                .addIdentifier("9613")
                .addName("NADCON")
                .createGroup(LATITUDE, LONGITUDE);
    }

    /**
     * Creates a new provider.
     */
    public NADCON() {
        super(2, 2, PARAMETERS);
    }

    /**
     * Returns the base interface of the {@code CoordinateOperation} instances that use this method.
     *
     * @return fixed to {@link Transformation}.
     */
    @Override
    public Class<Transformation> getOperationType() {
        return Transformation.class;
    }

    /**
     * Creates a transform from the specified group of parameter values.
     *
     * @param  factory  the factory to use if this constructor needs to create other math transforms.
     * @param  values   the group of parameter values.
     * @return the created math transform.
     * @throws ParameterNotFoundException if a required parameter was not found.
     * @throws FactoryException if an error occurred while loading the grid.
     */
    @Override
    public MathTransform createMathTransform(final MathTransformFactory factory, final ParameterValueGroup values)
            throws ParameterNotFoundException, FactoryException
    {
        final Parameters pg  = Parameters.castOrWrap(values);
        return InterpolatedTransform.createGeodeticTransformation(factory,
                getOrLoad(pg.getMandatoryValue(LATITUDE), pg.getMandatoryValue(LONGITUDE)));
    }

    /**
     * Returns the grid of the given name. This method returns the cached instance if it still exists,
     * or load the grid otherwise.
     *
     * @param latitudeShifts   name of the grid file for latitude shifts.
     * @param longitudeShifts  name of the grid file for longitude shifts.
     */
    @SuppressWarnings("null")
    static DatumShiftGridFile<Angle,Angle> getOrLoad(final Path latitudeShifts, final Path longitudeShifts)
            throws FactoryException
    {
        final Path rlat = DataDirectory.DATUM_CHANGES.resolve(latitudeShifts).toAbsolutePath();
        final Path rlon = DataDirectory.DATUM_CHANGES.resolve(longitudeShifts).toAbsolutePath();
        final Object key = new AbstractMap.SimpleImmutableEntry<>(rlat, rlon);
        DatumShiftGridFile<?,?> grid = DatumShiftGridFile.CACHE.peek(key);
        if (grid == null) {
            final Cache.Handler<DatumShiftGridFile<?,?>> handler = DatumShiftGridFile.CACHE.lock(key);
            try {
                grid = handler.peek();
                if (grid == null) {
                    final Loader loader;
                    Path file = latitudeShifts;
                    try {
                        // Note: buffer size must be divisible by the size of 'float' data type.
                        final ByteBuffer buffer = ByteBuffer.allocate(4096).order(ByteOrder.LITTLE_ENDIAN);
                        final FloatBuffer fb = buffer.asFloatBuffer();
                        try (ReadableByteChannel in = Files.newByteChannel(rlat)) {
                            DatumShiftGridLoader.log(NADCON.class, CharSequences.commonPrefix(
                                    latitudeShifts.toString(), longitudeShifts.toString()).toString() + '…');
                            loader = new Loader(in, buffer, file);
                            loader.readGrid(fb, null, longitudeShifts);
                        }
                        buffer.clear();
                        file = longitudeShifts;
                        try (ReadableByteChannel in = Files.newByteChannel(rlon)) {
                            new Loader(in, buffer, file).readGrid(fb, loader, null);
                        }
                    } catch (IOException | NoninvertibleTransformException | RuntimeException e) {
                        throw DatumShiftGridLoader.canNotLoad("NADCON", file, e);
                    }
                    grid = DatumShiftGridCompressed.compress(loader.grid, null, loader.grid.accuracy);
                    grid = grid.useSharedData();
                }
            } finally {
                handler.putAndUnlock(grid);
            }
        }
        return grid.castTo(Angle.class, Angle.class);
    }




    /**
     * Loaders of NADCON data. Instances of this class exist only at loading time.
     * This class can read both binary and ASCII grid files.
     *
     * <h4>Binary format</h4>
     * NADCON binary files ({@code "*.las"} and {@code "*.los"}) are organized into records
     * with the first record containing the header information, followed by the shift data.
     * The length of each record (including header) depends on the number of columns.
     *
     * <p>Records are ordered from South to North. Each record (except the header) is an entire row of grid points,
     * with values ordered from West to East. Each value is a {@code float} encoded in little endian byte order.
     * Each record ends with a 4 byte separator.</p>
     *
     * <p>Record data use a different convention than the record header. The header uses degrees of angle with
     * positive values East. But the offset values after the header are in seconds of angle with positive values
     * West. The {@code DatumShiftGrid} returned by this loader uses the header convention, which also matches
     * the order in which offset values appear in each row.</p>
     *
     * @author  Martin Desruisseaux (Geomatys)
     * @author  Rueben Schulz (UBC)
     * @version 0.7
     * @since   0.7
     * @module
     */
    private static final class Loader extends DatumShiftGridLoader {
        /**
         * The length of the description in the header, in bytes.
         * <ul>
         *   <li>56 bytes of NADCON's identification: {@code "NADCON EXTRACTED REGION"}.</li>
         *   <li>8 bytes of "PGM" (unknown meaning).</li>
         * </ul>
         */
        private static final int DESCRIPTION_LENGTH = 64;

        /**
         * The first bytes that we expect to find the header (both binary and ASCII files).
         * We use that as the format signature.
         */
        private static final String NADCON = "NADCON";

        /**
         * Longitude and latitude of of the first value in the first record, in degrees.
         */
        private final float x0, y0;

        /**
         * The difference between longitude (<var>Δx</var>) and latitude (<var>Δy</var>) cells, in degrees.
         */
        private final float Δx, Δy;

        /**
         * Number of longitude (<var>nx</var>) and latitude (<var>ny</var>) values.
         */
        private final int nx, ny, nz;

        /**
         * Temporary buffer for ASCII characters, or {@code null} if the file is a binary file.
         */
        private final StringBuilder ascii;

        /**
         * The grid created by {@link #readGrid(FloatBuffer, Loader, Path)}.
         */
        DatumShiftGridFile.Float<Angle,Angle> grid;

        /**
         * Creates a new reader for the given channel. The file can be binary or ASCII.
         * This constructor parses the header immediately, but does not read any grid.
         *
         * @param channel  where to read data from.
         * @param buffer   the buffer to use. That buffer must use little endian byte order
         *                 and have a capacity divisible by the size of the {@code float} type.
         * @param file     path to the longitude or latitude difference file. Used for parameter declaration and error reporting.
         */
        Loader(final ReadableByteChannel channel, final ByteBuffer buffer, final Path file)
                throws IOException, FactoryException
        {
            super(channel, buffer, file);
            // After the description we need (3 int + 5 float) = 32 bytes
            // for a binary header, or 74 characters for an ASCII header.
            ensureBufferContains(DESCRIPTION_LENGTH + 80);
            for (int i=0; i<NADCON.length(); i++) {
                if (buffer.get() != NADCON.charAt(i)) {
                    throw unexpectedFormat();
                }
            }
            if (isASCII(buffer)) {
                ascii = new StringBuilder();
                nx = Integer.parseInt(nextWord());
                ny = Integer.parseInt(nextWord());
                nz = Integer.parseInt(nextWord());
                x0 = Float.parseFloat(nextWord());
                Δx = Float.parseFloat(nextWord());
                y0 = Float.parseFloat(nextWord());
                Δy = Float.parseFloat(nextWord());
                     Float.parseFloat(nextWord());
            } else {
                ascii = null;
                buffer.position(DESCRIPTION_LENGTH);
                nx = buffer.getInt();     // Number of data elements in each record.
                ny = buffer.getInt();     // Number of records in the file.
                nz = buffer.getInt();     // Not used.
                x0 = buffer.getFloat();   // Longitude of first record (westmost).
                Δx = buffer.getFloat();   // Cell size in degrees of longitude.
                y0 = buffer.getFloat();   // Latitude of first record (southmost).
                Δy = buffer.getFloat();   // Cell size in degrees of latitude.
                                          // One more float at this position, which we ignore.
            }
            if (nx < 8 || ny < 1 || nz < 1 || !(Δx > 0) || !(Δy > 0) || Float.isNaN(x0) || Float.isNaN(y0)) {
                throw unexpectedFormat();
            }
            if (ascii == null) {
                skip((nx + 1) * Float.BYTES - buffer.position());
            }
        }

        /**
         * Returns {@code true} if all remaining characters in the buffer are US-ASCII characters for real numbers,
         * except the characters on the first line which may be any printable US-ASCII characters. If the content is
         * assumed ASCII, then the buffer position is set to the first EOL character.
         *
         * @return {@code true} if the file seems to be an ASCII one.
         */
        private static boolean isASCII(final ByteBuffer buffer) {
            int newLine = 0;
            while (buffer.hasRemaining()) {
                final char c = (char) buffer.get();
                if (c != ' ' && !(c >= '+' && c <= '9' && c != ',' && c != '/')) {          // (space) + - . [0-9]
                    if (c == '\r' || c == '\n') {
                        if (newLine == 0) {
                            newLine = buffer.position();
                        }
                    } else {
                        if (newLine == 0 && c >= 32 & c <= 126) {
                            continue;                   // Accept other US-ASCII characters ony on the first line.
                        }
                        return false;
                    }
                }
            }
            if (newLine == 0) {
                return false;          // If it was an ASCII file, we would have found at least one EOL character.
            }
            buffer.position(newLine);
            return true;
        }

        /**
         * Returns the next word from an ASCII file. This method is invoked only for parsing ASCII files,
         * in which case the {@link #ascii} string builder is non-null.
         */
        private String nextWord() throws IOException {
            char c;
            do {
                ensureBufferContains(1);
                c = (char) buffer.get();
            } while (Character.isWhitespace(c));
            ascii.setLength(0);
            do {
                ascii.append(c);
                ensureBufferContains(1);
                c = (char) buffer.get();
            } while (!Character.isWhitespace(c));
            return ascii.toString();
        }

        /**
         * Returns the exception to thrown in the file does not seems to be a NADCON format.
         */
        private FactoryException unexpectedFormat() {
            return new FactoryException(Errors.format(Errors.Keys.UnexpectedFileFormat_2, NADCON, file));
        }

        /**
         * Loads latitude or longitude shifts data. This method should be invoked twice:
         *
         * <ol>
         *   <li>On an instance created for the latitude shifts file with a {@code latitude} argument set to null.</li>
         *   <li>On an instance created for the longitude shifts file with a {@code latitude} argument set to the
         *       instance created in the previous step.</li>
         * </ol>
         *
         * The result is stored in the {@link #grid} field.
         *
         * @param fb               a {@code FloatBuffer} view over the full {@link #buffer} range.
         * @param latitudeShifts   the previously loaded latitude shifts, or {@code null} if not yet loaded.
         * @param longitudeShifts  the file for the longitude grid.
         */
        final void readGrid(final FloatBuffer fb, final Loader latitudeShifts, final Path longitudeShifts)
                throws IOException, FactoryException, NoninvertibleTransformException
        {
            final int dim;
            final double scale;
            if (latitudeShifts == null) {
                dim   = 1;                                              // Dimension of latitudes.
                scale = DEGREES_TO_SECONDS * Δy;                        // NADCON shifts are positive north.
                grid  = new DatumShiftGridFile.Float<>(2, Units.DEGREE, Units.DEGREE,
                        true, x0, y0, Δx, Δy, nx, ny, PARAMETERS, file, longitudeShifts);
                grid.accuracy = SECOND_PRECISION / DEGREES_TO_SECONDS;
            } else {
                if (x0 != latitudeShifts.x0 || Δx != latitudeShifts.Δx || nx != latitudeShifts.nx ||
                    y0 != latitudeShifts.y0 || Δy != latitudeShifts.Δy || ny != latitudeShifts.ny || nz != latitudeShifts.nz)
                {
                    throw new FactoryException(Errors.format(Errors.Keys.MismatchedGridGeometry_2,
                            latitudeShifts.file.getFileName(), file.getFileName()));
                }
                dim   = 0;                                              // Dimension of longitudes
                scale = -DEGREES_TO_SECONDS * Δx;                       // NADCON shifts are positive west.
                grid  = latitudeShifts.grid;                            // Continue writing in existing grid.
            }
            final float[] array = grid.offsets[dim];
            if (ascii != null) {
                for (int i=0; i<array.length; i++) {
                    array[i] = (float) (Double.parseDouble(nextWord()) / scale);
                }
            } else {
                /*
                 * Transfer all data from the FloatBuffer to the float[] array, except one float at the beginning
                 * of every row which must be skipped. That skipped float value is not a translation value and is
                 * expected to be always zero.
                 */
                syncView(fb);
                int forCurrentRow = 0;
                for (int i=0; i<array.length;) {
                    if (forCurrentRow == 0) {
                        if (!fb.hasRemaining()) {
                            fillBuffer(fb);
                        }
                        if (fb.get() != 0) {
                            throw unexpectedFormat();
                        }
                        forCurrentRow = nx;
                    }
                    int remaining = fb.remaining();
                    if (remaining == 0) {
                        fillBuffer(fb);
                        remaining = fb.remaining();
                    }
                    final int n = Math.min(forCurrentRow, remaining);
                    fb.get(array, i, n);
                    forCurrentRow -= n;
                    i += n;
                }
                /*
                 * Convert seconds to degrees for consistency with the unit declared at the beginning of this method,
                 * then divide by cell size for consistency with the 'isCellRatio = true' configuration.
                 */
                for (int i=0; i<array.length; i++) {
                    array[i] /= scale;
                }
            }
        }

        /**
         * Invoked when the given {@code FloatBuffer} buffer is empty. This method requests one {@code float}
         * from the channel, but the channel will usually give us as many data as the buffer can contain.
         */
        private void fillBuffer(final FloatBuffer fb) throws IOException {
            buffer.position(fb.position() * Float.BYTES).limit(fb.limit() * Float.BYTES);
            ensureBufferContains(Float.BYTES);  // Require at least one float, but usually get many.
            syncView(fb);
        }

        /**
         * Sets the position and limit of the given {@code FloatBuffer} to the same position and limit
         * than the underlying {@code ByteBuffer}, converted to units of {@code float} data type.
         */
        private void syncView(final FloatBuffer fb) {
            if ((buffer.position() % Float.BYTES) != 0) {
                buffer.compact();                               // For bytes alignment with FloatBuffer.
            }
            fb.limit(buffer.limit() / Float.BYTES).position(buffer.position() / Float.BYTES);
        }
    }
}
