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

import java.util.AbstractList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.EnumMap;
import java.util.TreeMap;
import java.util.NavigableMap;
import java.util.function.BiConsumer;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.CompletionException;
import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.image.RenderedImage;
import org.opengis.coverage.grid.SequenceType;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.internal.processing.image.TiledProcess;
import org.apache.sis.image.PixelIterator;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.Debug;

import static org.apache.sis.internal.processing.isoline.Tracer.UPPER_LEFT;
import static org.apache.sis.internal.processing.isoline.Tracer.UPPER_RIGHT;
import static org.apache.sis.internal.processing.isoline.Tracer.LOWER_RIGHT;


/**
 * Creates isolines at specified levels from grid values provided in a {@link RenderedImage}.
 * Isolines are created by calls to the {@link #generate generate(…)} static method.
 *
 * @author  Johann Sorel (Geomatys)
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.3
 *
 * @see <a href="https://en.wikipedia.org/wiki/Marching_squares">Marching squares on Wikipedia</a>
 *
 * @since 1.1
 * @module
 */
public final class Isolines {
    /**
     * Isoline data for each level, sorted in ascending order of {@link Tracer.Level#value}.
     */
    private final Tracer.Level[] levels;

    /**
     * A consumer to notify about the current state of isoline generation, or {@code null} if none.
     * This is used for debugging purposes only. This field is temporarily set to a non-null value
     * when using {@code StepsViewer} (in test package) for following an isoline generation step
     * by step.
     */
    @Debug
    private static final BiConsumer<String,Isolines> LISTENER = null;

    /**
     * Creates an initially empty set of isolines for the given levels. The given {@code values}
     * array should be one of the arrays validated by {@link #cloneAndSort(double[][])}.
     */
    private Isolines(final Tracer tracer, final int band, final double[] values, final int width) {
        levels = new Tracer.Level[values.length];
        for (int i=0; i<values.length; i++) {
            levels[i] = tracer.new Level(band, values[i], width);
        }
    }

    /**
     * Ensures that the given arrays are sorted and contains no NaN value.
     */
    private static double[][] cloneAndSort(double[][] levels) {
        levels.clone();
        for (int j=0; j<levels.length; j++) {
            double[] values = levels[j];
            ArgumentChecks.ensureNonNullElement("levels", j, values);
            values = values.clone();
            Arrays.sort(values);
            int n = values.length;
            while (n > 0 && Double.isNaN(values[n-1])) n--;
            for (int i=n; --i>0;) {
                if (values[i] == values[i-1]) {
                    // Remove duplicated elements. May replace -0 by +0.
                    System.arraycopy(values, i, values, i-1, n-- - i);
                }
            }
            levels[j] = ArraysExt.resize(values, n);
        }
        return levels;
    }

    /**
     * Sets the specified bit on {@link Tracer.Level#isDataAbove} for all levels lower than given value.
     *
     * <h4>How strict equalities are handled</h4>
     * Sample values exactly equal to the isoline value are handled as if they were greater. It does not matter
     * for interpolations: we could flip this convention randomly, the interpolated points would still the same.
     * However it could change the way line segments are assembled in a single polyline, but the algorithm stay
     * consistent if we always apply the same rule for all points.
     *
     * <h4>How NaN values are handled</h4>
     * {@link Double#NaN} sample values are considered higher than any level values. The algorithm does not need
     * special attention for those values; bit patterns will be computed in a consistent way, and interpolations
     * will produce NaN values and append them to polylines like real values.  Those NaN values will be filtered
     * out in the final stage, when copying coordinates in {@link Path2D} objects.
     *
     * @param  value a sample values from the image.
     * @param  bit   {@value Tracer#UPPER_LEFT}, {@value Tracer#UPPER_RIGHT},
     *               {@value Tracer#LOWER_LEFT} or {@value Tracer#LOWER_RIGHT}.
     *
     * @see Tracer.Level#nextColumn()
     */
    private void setMaskBit(final double value, final int bit) {
        for (final Tracer.Level level : levels) {
            if (level.value > value) break;                 // See above javadoc for NaN handling.
            level.isDataAbove |= bit;
        }
    }

    /**
     * Generates isolines at the specified levels computed from data provided by the given image.
     * Isolines will be created for every bands in the given image.
     * This method performs all computation sequentially in current thread.
     *
     * @param  data       image providing source values.
     * @param  levels     values for which to compute isolines. An array should be provided for each band.
     *                    If there is more bands than {@code levels.length}, the last array is reused for
     *                    all remaining bands.
     * @param  gridToCRS  transform from pixel coordinates to geometry coordinates, or {@code null} if none.
     *                    Integer source coordinates are located at pixel centers.
     * @return the isolines for each band in the given image.
     * @throws TransformException if an interpolated point can not be transformed using the given transform.
     */
    public static Isolines[] generate(final RenderedImage data, final double[][] levels,
                                      final MathTransform gridToCRS) throws TransformException
    {
        ArgumentChecks.ensureNonNull("data",   data);
        ArgumentChecks.ensureNonNull("levels", levels);
        return flush(generate(iterators().create(data), cloneAndSort(levels), gridToCRS));
    }

    /**
     * Generates isolines in background using an arbitrary amount of processors.
     * This method returns immediately (i.e. the current thread is not used for isoline computation).
     * The result will become available at a later time in the {@link Future} object.
     *
     * @param  data       image providing source values.
     * @param  levels     values for which to compute isolines. An array should be provided for each band.
     *                    If there is more bands than {@code levels.length}, the last array is reused for
     *                    all remaining bands.
     * @param  gridToCRS  transform from pixel coordinates to geometry coordinates, or {@code null} if none.
     *                    Integer source coordinates are located at pixel centers.
     * @return a {@code Future} representing pending completion of isoline computation.
     */
    public static Future<Isolines[]> parallelGenerate(final RenderedImage data, final double[][] levels,
                                                      final MathTransform gridToCRS)
    {
        ArgumentChecks.ensureNonNull("data",   data);
        ArgumentChecks.ensureNonNull("levels", levels);
        return new Process(data, cloneAndSort(levels), gridToCRS).execute();
    }

    /**
     * Returns a provider of {@link PixelIterator} suitable to isoline computations.
     * It is critical that iterators use {@link SequenceType#LINEAR} iterator order.
     */
    private static PixelIterator.Builder iterators() {
        return new PixelIterator.Builder().setIteratorOrder(SequenceType.LINEAR);
    }

    /**
     * Creates all polylines that were still pending. This method should be the very last step,
     * when all other computations finished. Pending polylines are sequences of points not yet
     * stored in geometry objects because they were waiting to see if additional points would
     * close them as polygons. This {@code flush()} method is invoked when we know that it will
     * not be the case because there are no more points to add.
     *
     * @param  isolines  the isolines for which to write pending polylines.
     * @return the {@code isolines} array, returned for convenience.
     * @throws TransformException if an error occurred during polylines creation.
     */
    private static Isolines[] flush(final Isolines[] isolines) throws TransformException {
        for (final Isolines isoline : isolines) {
            for (final Tracer.Level level : isoline.levels) {
                level.flush();
            }
        }
        return isolines;
    }

    /**
     * Wraps {@code Isolines.generate(…)} calculation in a process for parallel execution.
     * The source image is divided in sub-region and the isolines in each sub-region will
     * be computed in a different thread.
     */
    private static final class Process extends TiledProcess<Isolines[]> {
        /**
         * Values for which to compute isolines. An array should be provided for each band.
         * If there is more bands than {@code levels.length}, the last array is reused for
         * all remaining bands.
         *
         * @see #cloneAndSort(double[][])
         */
        private final double[][] levels;

        /**
         * Transform from image upper left corner (in pixel coordinates) to geometry coordinates.
         */
        private final MathTransform gridToCRS;

        /**
         * Creates a process for parallel isoline computation.
         *
         * @param  data       image providing source values.
         * @param  levels     values for which to compute isolines.
         * @param  gridToCRS  transform from pixel coordinates to geometry coordinates, or {@code null} if none.
         */
        Process(final RenderedImage data, final double[][] levels, final MathTransform gridToCRS) {
            super(data, 1, 1, iterators());
            this.levels = levels;
            this.gridToCRS = gridToCRS;
        }

        /**
         * Invoked by {@link TiledProcess} for creating a sub-task
         * doing isoline computation on a sub-region of the image.
         */
        @Override
        protected Task createSubTask() {
            return new Tile();
        }

        /**
         * A sub-task doing isoline computation on a sub-region of the image.
         * The region is determined by the {@link #iterator}.
         */
        private final class Tile extends Task {
            /** Isolines computed in the sub-region of this sub-task. */
            private Isolines[] isolines;

            /** Creates a new sub-task. */
            Tile() {
            }

            /** Invoked in a background thread for performing isoline computation. */
            @Override protected void execute() throws TransformException {
                isolines = generate(iterator, levels, gridToCRS);
            }

            /** Invoked in a background thread for merging results of two sub-tasks. */
            @Override protected void merge(final Task neighbor) throws TransformException {
                for (int i=0; i<isolines.length; i++) {
                    final Isolines target = isolines[i];
                    final Isolines source = ((Tile) neighbor).isolines[i];
                    for (int j=0; j<target.levels.length; j++) {
                        target.levels[j].merge(source.levels[j]);
                    }
                }
            }

            /** Invoked on the last sub-task (after all merges) for getting final result. */
            @Override protected Isolines[] result() throws TransformException {
                return flush(isolines);
            }
        }
    }

    /**
     * Generates isolines for the specified levels in the region traversed by the given iterator.
     * This is the implementation of {@link #generate(RenderedImage, double[][], MathTransform)}
     * but potentially on a sub-region for parallel "fork-join" execution.
     */
    private static Isolines[] generate(final PixelIterator iterator, final double[][] levels,
                                       final MathTransform gridToCRS) throws TransformException
    {
        /*
         * Prepares a window of size 2×2 pixels over pixel values. Window elements are traversed
         * by incrementing indices in following order: band, column, row. The window content will
         * be written in this method and read by Tracer.
         */
        final int numBands = iterator.getNumBands();
        final double[] window = new double[numBands * 4];
        final Tracer tracer = new Tracer(window, numBands, iterator.getDomain(), gridToCRS);
        /*
         * Prepare the set of isolines for each band in the image.
         * The number of cells on the horizontal axis is one less
         * than the image width.
         */
        final int width = iterator.getDomain().width - 1;
        final Isolines[] isolines = new Isolines[numBands];
        {   // For keeping variable locale.
            double[] levelValues = ArraysExt.EMPTY_DOUBLE;
            for (int b=0; b<numBands; b++) {
                if (b < levels.length) {
                    levelValues = levels[b];
                    ArgumentChecks.ensureNonNullElement("levels", b, levelValues);
                    levelValues = levelValues.clone();
                }
                isolines[b] = new Isolines(tracer, b, levelValues, width);
            }
        }
        /*
         * Cache sample values on the top row. Those values are reused by the row just below row
         * of cached values. This array is updated during iteration with values of current cell.
         */
        final double[] pixelValues = new double[numBands];
        final double[] valuesOnPreviousRow = new double[numBands * (width+1)];
        for (int i=0; i < valuesOnPreviousRow.length; i += numBands) {
            if (!iterator.next()) return isolines;
            System.arraycopy(iterator.getPixel(pixelValues), 0, valuesOnPreviousRow, i, numBands);
        }
        /*
         * Compute isolines for all bands. Iteration over bands must be the innermost loop because
         * data layout in buffer is band index varying fastest, then column index, then row index.
         */
        final int twoPixels = numBands * 2;
        final int lastPixel = numBands * 3;
abort:  while (iterator.next()) {
            /*
             * Process the first cell of a new row:
             *
             *  - Get values on the 4 corners.
             *  - Save value of lower-left corner for use by next row.
             *  - Initialize `Tracer.Level.isDataAbove` bits for all levels.
             *  - Interpolate the first cell.
             */
            System.arraycopy(valuesOnPreviousRow, 0, window, 0, twoPixels);
            System.arraycopy(iterator.getPixel(pixelValues), 0, window, twoPixels, numBands);
            if (!iterator.next()) break;
            System.arraycopy(iterator.getPixel(pixelValues), 0, window, lastPixel, numBands);
            System.arraycopy(window, twoPixels, valuesOnPreviousRow, 0, twoPixels);
            for (int i=0, flag = UPPER_LEFT; flag <= LOWER_RIGHT; flag <<= 1) {
                for (int b=0; b<numBands; b++) {        // Must be the inner loop (see above comment).
                    isolines[b].setMaskBit(window[i++], flag);
                }
            }
            for (final Isolines iso : isolines) {
                for (final Tracer.Level level : iso.levels) {
                    level.interpolate();
                }
            }
            /*
             * Process all pixels on a row after the first column. We can reuse the bitmask of previous
             * iteration with a simple bit shift operation. This is done by the `nextColumn()` call.
             * The series for `System.arraycopy(…)` calls are for moving 3 pixel values of previous
             * iteration that we can reuse, then fetch the only new value from the iterator.
             */
            for (tracer.x = 1; tracer.x < width; tracer.x++) {
                final int offsetOnPreviousRow = (tracer.x + 1) * numBands;
                if (!iterator.next()) break abort;                              // Should never abort
                if (numBands == 1) {                                            // Optimization for a common case
                    window[2] = window[3];                                      // Lower-right → Lower-left
                    window[0] = window[1];                                      // Upper-right → Upper-left
                    window[1] = valuesOnPreviousRow[offsetOnPreviousRow];       // Take upper-right from previous row
                    window[3] = valuesOnPreviousRow[offsetOnPreviousRow] = iterator.getSampleDouble(0);
                } else {
                    System.arraycopy(window, numBands,  window, 0,         numBands);   // Upper-right → Upper-left
                    System.arraycopy(window, lastPixel, window, twoPixels, numBands);   // Lower-right → Lower-left
                    System.arraycopy(valuesOnPreviousRow, offsetOnPreviousRow, window, numBands, numBands);
                    System.arraycopy(iterator.getPixel(pixelValues), 0, window, lastPixel, numBands);
                    System.arraycopy(window, lastPixel, valuesOnPreviousRow, offsetOnPreviousRow, numBands);
                }
                for (int b=0; b<numBands; b++) {
                    final Isolines iso = isolines[b];
                    for (final Tracer.Level level : iso.levels) {
                        level.nextColumn();
                    }
                    iso.setMaskBit(window[numBands  + b], UPPER_RIGHT);
                    iso.setMaskBit(window[lastPixel + b], LOWER_RIGHT);
                    for (final Tracer.Level level : iso.levels) {
                        level.interpolate();
                    }
                }
            }
            /*
             * Finished iteration on a row. Clear flags and update position before to move to next row.
             * If there is listeners to notify (for debugging purposes), notify them.
             */
            for (int b=0; b<numBands; b++) {
                for (final Tracer.Level level : isolines[b].levels) {
                    level.finishedRow();
                }
                if (LISTENER != null) {
                    final int y = tracer.y;
                    final int h = iterator.getDomain().height;
                    LISTENER.accept(String.format("After row %d of %d (%3.1f%%)", y, h, 100f*y/h), isolines[b]);
                }
            }
            tracer.x = 0;
            tracer.y++;
        }
        /*
         * Finished iteration over the whole image.
         */
        for (int b=0; b<numBands; b++) {
            for (final Tracer.Level level : isolines[b].levels) {
                level.finish();
            }
            if (LISTENER != null) {
                LISTENER.accept("Finished band " + b, isolines[b]);
            }
        }
        return isolines;
    }

    /**
     * Returns the polylines for each level specified to the {@link #generate generate(…)} method.
     *
     * @return the polylines for each level.
     */
    public final NavigableMap<Double,Shape> polylines() {
        final TreeMap<Double,Shape> paths = new TreeMap<>();
        for (final Tracer.Level level : levels) {
            final Shape path = level.shape;
            if (path != null) {
                paths.put(level.value, path);
            }
        }
        return paths;
    }

    /**
     * Returns the isolines for each band, then for each values in the band.
     *
     * @param  isolines  result of {@code generate(…)} or {@code parallelGenerate(…)} method call.
     * @return isoline shapes for each values in each band.
     */
    private static NavigableMap<Double,Shape>[] toArray(final Isolines[] isolines) {
        @SuppressWarnings({"rawtypes", "unchecked"})
        final NavigableMap<Double,Shape>[] result = new NavigableMap[isolines.length];
        for (int i=0; i<result.length; i++) {
            result[i] = isolines[i].polylines();
        }
        return result;
    }

    /**
     * Returns the isolines for each band, then for each values in the band.
     *
     * @param  isolines  result of {@code generate(…)} or {@code parallelGenerate(…)} method call.
     * @return isoline shapes for each values in each band.
     */
    public static List<NavigableMap<Double,Shape>> toList(final Isolines[] isolines) {
        return Arrays.asList(toArray(isolines));
    }

    /**
     * Returns deferred isolines for each band, then for each values in the band.
     * The {@link Future} result is requested the first time that {@link List#get(int)} is invoked.
     *
     * @param  isolines  result of {@code generate(…)} or {@code parallelGenerate(…)} method call.
     * @return isoline shapes for each values in each band.
     */
    public static List<NavigableMap<Double,Shape>> toList(final Future<Isolines[]> isolines) {
        return new Result(isolines);
    }

    /**
     * Deferred isoline result, created when computation is continuing in background.
     * The {@link Future} result is requested the first time that {@link #get(int)} is invoked.
     */
    private static final class Result extends AbstractList<NavigableMap<Double,Shape>> {
        /** The task computing isolines result. Reset to {@code null} when no longer needed. */
        private Future<Isolines[]> task;

        /** The result of {@link Future#get()} fetched when first needed. */
        private NavigableMap<Double,Shape>[] isolines;

        /** Creates a new list for the given future isolines. */
        Result(final Future<Isolines[]> task) {
            this.task = task;
        }

        /** Fetches the isolines from the {@link Future} if not already done. */
        @SuppressWarnings("ReturnOfCollectionOrArrayField")
        private NavigableMap<Double,Shape>[] isolines() {
            if (isolines == null) {
                if (task == null) {
                    throw new CompletionException(Errors.format(Errors.Keys.BackgroundComputationFailed), null);
                }
                try {
                    isolines = Isolines.toArray(task.get());
                    task = null;
                } catch (InterruptedException e) {
                    // Do not clear `task`: the result may become available later.
                    throw new CompletionException(Errors.format(Errors.Keys.InterruptedWhileWaitingResult), e);
                } catch (ExecutionException e) {
                    task = null;
                    throw new CompletionException(Errors.format(Errors.Keys.BackgroundComputationFailed), e.getCause());
                }
            }
            return isolines;
        }

        /** Returns the list length, which is the number of bands. */
        @Override public int size() {
            return isolines().length;
        }

        /** Returns the isolines in the given band. */
        @Override public NavigableMap<Double,Shape> get(final int band) {
            return isolines()[band];
        }

        /** Returns the list content as an array. */
        @Override public Object[] toArray() {
            return isolines().clone();
        }
    }

    /**
     * Returns the pixel coordinates of all level, for debugging purposes only.
     * The {@link #gridToCRS} transform is <em>not</em> applied by this method.
     * For avoiding confusing behavior, that transform should be null.
     *
     * @return the pixel coordinates.
     */
    @Debug
    final Map<PolylineStage,Path2D> toRawPath() {
        final Map<PolylineStage,Path2D> appendTo = new EnumMap<>(PolylineStage.class);
        for (final Tracer.Level level : levels) {
            level.toRawPath(appendTo);
        }
        return appendTo;
    }
}
