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

import java.util.Arrays;
import java.util.Random;
import java.util.EnumSet;
import java.util.stream.IntStream;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.opengis.util.FactoryException;
import static org.opengis.referencing.datum.PixelInCell.CELL_CENTER;
import org.apache.sis.geometry.Envelope2D;
import org.apache.sis.geometry.DirectPosition2D;
import org.apache.sis.geometry.ImmutableEnvelope;
import org.apache.sis.image.Interpolation;
import org.apache.sis.coverage.privy.TiledImage;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.privy.Formulas;
import org.apache.sis.referencing.privy.AffineTransform2D;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.referencing.operation.matrix.MatrixSIS;
import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.referencing.operation.transform.TransformSeparator;

// Test dependencies
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.sis.test.TestCase;
import org.apache.sis.test.TestUtilities;
import org.apache.sis.image.TiledImageMock;
import org.apache.sis.referencing.crs.HardCodedCRS;
import org.apache.sis.referencing.operation.HardCodedConversions;
import static org.apache.sis.referencing.Assertions.assertEnvelopeEquals;
import static org.apache.sis.feature.Assertions.assertValuesEqual;
import static org.apache.sis.feature.Assertions.assertPixelsEqual;

// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import static org.opengis.test.Assertions.assertSampleValuesEqual;
import static org.opengis.test.Assertions.assertAxisDirectionsEqual;


/**
 * Tests the {@link ResampledGridCoverage} implementation.
 * The tests in this class does not verify interpolation results
 * (this is {@link org.apache.sis.image.ResampledImageTest} job).
 * Instead, it focuses on the grid geometry inferred by the operation.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @author  Alexis Manin (Geomatys)
 * @author  Johann Sorel (Geomatys)
 */
public final class ResampledGridCoverageTest extends TestCase {
    /**
     * The random number generator used for generating some grid coverage values.
     * Created only if needed.
     */
    private Random random;

    /**
     * Arbitrary non-zero grid coordinate for the <var>z</var> dimensions.
     */
    private int gridZ;

    /**
     * Creates a new test case.
     */
    public ResampledGridCoverageTest() {
    }

    /**
     * Creates a small grid coverage with arbitrary data. The rendered image will
     * have only one tile because testing tiling is not the purpose of this class.
     * This simple coverage is two-dimensional.
     */
    private GridCoverage2D createCoverage2D() {
        random = TestUtilities.createRandomNumberGenerator();
        final int width  = random.nextInt(8) + 3;
        final int height = random.nextInt(8) + 3;
        final TiledImageMock image = new TiledImageMock(
                DataBuffer.TYPE_USHORT, 2,      // dataType and numBands
                random.nextInt(32) - 10,        // minX (no effect on tests)
                random.nextInt(32) - 10,        // minY (no effect on tests)
                width, height,                  // Image size
                width, height,                  // Tile size
                random.nextInt(32) - 10,        // minTileX
                random.nextInt(32) - 10,        // minTileY
                random.nextBoolean());          // Banded or interleaved sample model
        image.validate();
        image.initializeAllTiles(0);
        final int x = random.nextInt(32) - 10;
        final int y = random.nextInt(32) - 10;
        final GridGeometry gg = new GridGeometry(
                new GridExtent(null, new long[] {x, y}, new long[] {x+width, y+height}, false),
                new Envelope2D(HardCodedCRS.WGS84, 20, 15, 60, 62), GridOrientation.HOMOTHETY);
        return new GridCoverage2D(gg, null, image);
    }

    /**
     * Size of a quadrant in the coverage created by {@link #createCoverageND(boolean)}.
     * The total image width and height are {@code 2*Q}.
     */
    private static final int QS = 3;

    /**
     * Low values for the grid extent created by {@link #createCoverage2D()}.
     */
    private static final int LX = 3, LY = -2;

    /**
     * Creates a coverage in {@linkplain HardCodedCRS#WGS84_3D OGC:CRS:84 + elevation} reference system.
     * If the {@code withTime} argument is {@code true}, then the coverage will also include a temporal
     * dimension. The grid coverage characteristics are:
     * <ul>
     *   <li>Dimension is 6×6.</li>
     *   <li>Grid extent starts at arbitrary non-zero low values.</li>
     *   <li>Envelope is arbitrary but stable (no random values).</li>
     *   <li>Display oriented (origin is in upper-left corner).</li>
     *   <li>3 byte bands for RGB coloration.</li>
     *   <li>Each quarter of the overall image is filled with a plain color:
     *     <table style="color:white;border-collapse:collapse;">
     *       <tbody style="border:none">
     *         <tr>
     *           <td style="width:50%; background-color:black">Black</td>
     *           <td style="width:50%; background-color:red">Red</td>
     *         </tr>
     *         <tr>
     *           <td style="width:50%; background-color:green">Green</td>
     *           <td style="width:50%; background-color:blue">Blue</td>
     *         </tr>
     *       </tbody>
     *     </table>
     *   </li>
     * </ul>
     *
     * @param  withTime  {@code false} for a three-dimensional coverage, or {@code true} for adding a temporal dimension.
     * @return a new three- or four-dimensional RGB Grid Coverage.
     */
    private GridCoverage createCoverageND(final boolean withTime) {
        random = TestUtilities.createRandomNumberGenerator();
        final BufferedImage image = new BufferedImage(2*QS, 2*QS, BufferedImage.TYPE_3BYTE_BGR);
        final int[] color = new int[QS*QS];
        /* Upper-left  quarter */ // Keep default value, which is black.
        /* Upper-right quarter */ Arrays.fill(color, Color.RED  .getRGB()); image.setRGB(QS,  0, QS, QS, color, 0, QS);
        /* Lower-left  quarter */ Arrays.fill(color, Color.GREEN.getRGB()); image.setRGB( 0, QS, QS, QS, color, 0, QS);
        /* Lower-right quarter */ Arrays.fill(color, Color.BLUE .getRGB()); image.setRGB(QS, QS, QS, QS, color, 0, QS);
        /*
         * Create an image with origin between -2 and +2. We use a random image location for more
         * complete testing, but actually the tests in this class are independent of image origin.
         * Note that grid extent origin does not need to be the same as image origin.
         */
        final int minX = random.nextInt(5) - 2;
        final int minY = random.nextInt(5) - 2;
        GridGeometry gg = createGridGeometryND(withTime ? HardCodedCRS.WGS84_4D : HardCodedCRS.WGS84_3D, 0, 1, 2, 3, false);
        final TiledImage shiftedImage = new TiledImage(null,
                image.getColorModel(),
                image.getWidth(), image.getHeight(),        // Image size
                random.nextInt(32) - 10,                    // minTileX
                random.nextInt(32) - 10,                    // minTileY
                image.getRaster().createTranslatedChild(minX, minY));
        return new GridCoverage2D(gg, null, shiftedImage);
    }

    /**
     * Creates the grid geometry associated with {@link #createCoverageND(boolean)}, optionally with swapped
     * horizontal axes and flipped Y axis. The given CRS shall have 3 or 4 dimensions.
     *
     * @param  crs    the coordinate reference system to assign to the grid geometry.
     * @param  x      dimension of <var>x</var> coordinates (typically 0).
     * @param  y      dimension of <var>y</var> coordinates (typically 1).
     * @param  z      dimension of <var>z</var> coordinates (typically 2).
     * @param  t      dimension of <var>t</var> coordinates (typically 3). Ignored if the CRS is not four-dimensional.
     * @param  flipY  whether to flip the <var>y</var> axis.
     */
    private GridGeometry createGridGeometryND(final CoordinateReferenceSystem crs,
            final int x, final int y, final int z, final int t, final boolean flipY)
    {
        final int dim = crs.getCoordinateSystem().getDimension();
        final long[] lower = new long[dim];
        final long[] upper = new long[dim];
        lower[x] = LX; upper[x] = LX + 2*QS - 1;
        lower[y] = LY; upper[y] = LY + 2*QS - 1;
        final MatrixSIS gridToCRS = Matrices.createIdentity(dim + 1);
        gridToCRS.setElement(x, x,    44./(2*QS));  // X scale
        gridToCRS.setElement(x, dim, -50./(2*QS));  // X translation
        gridToCRS.setElement(y, y,   -3.5);         // Y scale
        gridToCRS.setElement(y, dim, -0.75);        // Y translation
        gridToCRS.setElement(z, dim, -100);
        lower[z] = upper[z] = gridZ = 7;            // Arbitrary non-zero position in the grid.
        if (t < dim) {
            gridToCRS.setElement(t, dim, 48055);
            lower[t] = upper[t] = 12;
        }
        if (flipY) {
            /*
             * Lower Y coordinate before flip:    Ty₁ + scale × LY
             * Upper Y coordinate after flip:     Ty₂ − scale × (LY+2×QS−1)
             * Condition  Ty₁ = Ty₂  gives:       Ty₂ = Ty₁ + scale × (2(QS+LY)−1)
             */
            gridToCRS.setElement(y, y, 3.5);    // Inverse sign.
            gridToCRS.setElement(y, dim, -0.75 + -3.5 * (2*(QS+LY) - 1));
        }
        return new GridGeometry(new GridExtent(null, lower, upper, true),
                    CELL_CENTER, MathTransforms.linear(gridToCRS), crs);
    }

    /**
     * Verifies that the given target coverage has the same pixel values as the source coverage.
     * This method opportunistically verifies that the target {@link GridCoverage} instance has a
     * {@link GridCoverage#render(GridExtent)} implementation conforms to the specification, i.e.
     * that requesting only a sub-area results in an image where pixel coordinate (0,0) corresponds
     * to cell coordinates in the lower corner of specified {@code sliceExtent}.
     */
    private void assertContentEquals(final GridCoverage source, final GridCoverage target) {
        final int tx = random.nextInt(3);
        final int ty = random.nextInt(3);
        final GridExtent sourceExtent = source.gridGeometry.getExtent();
        final int newWidth   = StrictMath.toIntExact(sourceExtent.getSize(0) - tx);
        final int newHeight  = StrictMath.toIntExact(sourceExtent.getSize(1) - ty);
        GridExtent subExtent = new GridExtent(
                StrictMath.toIntExact(sourceExtent.getLow(0) + tx),
                StrictMath.toIntExact(sourceExtent.getLow(1) + ty),
                newWidth,
                newHeight
        );
        assertPixelsEqual(source.render(null), new Rectangle(tx, ty, newWidth, newHeight),
                          target.render(subExtent), new Rectangle(newWidth, newHeight));
    }

    /**
     * Returns a resampled coverage using processor with default configuration.
     * We use processor instead of instantiating {@link ResampledGridCoverage} directly in order
     * to test {@link GridCoverageProcessor#resample(GridCoverage, GridGeometry)} method as well.
     *
     * <p>{@link GridCoverageProcessor.Optimization#REPLACE_OPERATION} is disabled for avoiding to
     * test another operation than the resampling one.</p>
     */
    private static GridCoverage resample(final GridCoverage source, final GridGeometry target) throws TransformException {
        final GridCoverageProcessor processor = new GridCoverageProcessor();
        processor.setOptimizations(EnumSet.of(GridCoverageProcessor.Optimization.REPLACE_SOURCE));
        processor.setInterpolation(Interpolation.NEAREST);
        return processor.resample(source, target);
    }

    /**
     * Tests application of an identity transform computed from an explicitly given "grid to CRS" transform.
     * We expect the source coverage to be returned unchanged.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testExplicitIdentity() throws TransformException {
        final GridCoverage2D source = createCoverage2D();
        GridGeometry gg = source.getGridGeometry();
        gg = new GridGeometry(null, CELL_CENTER, gg.getGridToCRS(CELL_CENTER), gg.getCoordinateReferenceSystem());
        final GridCoverage target = resample(source, gg);
        assertSame(source, target, "Identity transform should result in same coverage.");
        assertContentEquals(source, target);
    }

    /**
     * Tests application of an identity transform without specifying explicitly the desired grid geometry.
     * This test is identical to {@link #testExplicitIdentity()} except that the "grid to CRS" transform
     * specified to the {@code resample(…)} operation is null.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testImplicitIdentity() throws TransformException {
        final GridCoverage2D source = createCoverage2D();
        GridGeometry gg = source.getGridGeometry();
        gg = new GridGeometry(null, CELL_CENTER, null, gg.getCoordinateReferenceSystem());
        final GridCoverage target = resample(source, gg);
        assertSame(source, target, "Identity transform should result in same coverage.");
        assertContentEquals(source, target);
    }

    /**
     * Tests resampling with a transform which is only a translation by integer values.
     * This test verifies that an optimized path (much cheaper than real resampling) is taken.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testIntegerTranslation() throws TransformException {
        final GridCoverageProcessor processor = new GridCoverageProcessor();    // With all optimization enabled.
        final GridCoverage source   = createCoverage2D();
        final GridGeometry sourceGG = source.getGridGeometry();
        final GridGeometry targetGG = sourceGG.shiftGrid(-10, 15);
        final GridCoverage target   = processor.resample(source, targetGG);
        assertInstanceOf(TranslatedGridCoverage.class, target, "Expected fast path.");
        assertSame(targetGG, target.getGridGeometry());
        assertEnvelopeEquals(sourceGG.getEnvelope(), targetGG.getEnvelope(), STRICT);
        /*
         * The envelope is BOX(20 15, 80 77). Evaluate a single point inside that envelope.
         * The result for identical "real world" coordinates should be the same for both coverages.
         */
        final DirectPosition2D p = new DirectPosition2D(sourceGG.getCoordinateReferenceSystem(), 50, 30);
        assertArrayEquals(source.evaluator().apply(p),
                          target.evaluator().apply(p));
    }

    /**
     * Tests application of axis swapping in a two-dimensional coverage.
     * This test verifies the envelope of resampled coverage.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testAxisSwap() throws TransformException {
        final GridCoverage2D source = createCoverage2D();
        GridGeometry gg = new GridGeometry(null, CELL_CENTER, null, HardCodedCRS.WGS84_LATITUDE_FIRST);
        final GridCoverage target = resample(source, gg);
        /*
         * We expect the same image since `ResampledGridCoverage` should have been
         * able to apply the operation with only a change of `gridToCRS` transform.
         */
        assertNotSame(source, target);
        assertSame(unwrap(source.render(null)),
                   unwrap(target.render(null)));
        /*
         * As an easy way to check that axis swapping has happened, check the envelopes.
         */
        final ImmutableEnvelope se = source.getGridGeometry().envelope;
        final ImmutableEnvelope te = target.getGridGeometry().envelope;
        assertEquals(se.getLower(0), te.getLower(1), Formulas.ANGULAR_TOLERANCE);
        assertEquals(se.getLower(1), te.getLower(0), Formulas.ANGULAR_TOLERANCE);
        assertEquals(se.getUpper(0), te.getUpper(1), Formulas.ANGULAR_TOLERANCE);
        assertEquals(se.getUpper(1), te.getUpper(0), Formulas.ANGULAR_TOLERANCE);
    }

    /**
     * Unwraps the given image if it is an instance of {@link ReshapedImage}.
     */
    private static RenderedImage unwrap(final RenderedImage image) {
        assertEquals(0, image.getMinX(), "GridCoverage.render(null) should have their origin at (0,0).");
        assertEquals(0, image.getMinY(), "GridCoverage.render(null) should have their origin at (0,0).");
        return (image instanceof ReshapedImage) ? ((ReshapedImage) image).source : image;
    }

    /**
     * Tests application of axis swapping in a three-dimensional coverage, together with an axis flip.
     * This test verifies that the pixel values of resampled coverage are found in expected quadrant.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testAxisSwapAndFlip() throws TransformException {
        final GridCoverage  source      = createCoverageND(false);
        final GridGeometry  target      = createGridGeometryND(CommonCRS.WGS84.geographic3D(), 1, 0, 2, 3, true);
        final GridCoverage  result      = resample(source, target);
        final RenderedImage sourceImage = source.render(null);
        final RenderedImage targetImage = result.render(null);
        assertEquals(target, result.getGridGeometry());
        assertEquals(0, sourceImage.getMinX());                     // As per GridCoverage.render(…) contract.
        assertEquals(0, sourceImage.getMinY());
        assertEquals(0, targetImage.getMinX());
        assertEquals(0, targetImage.getMinY());
        assertPixelsEqual(sourceImage, new Rectangle( 0, QS, QS, QS),
                          targetImage, new Rectangle( 0,  0, QS, QS));      // Green should be top-left.
        assertPixelsEqual(sourceImage, new Rectangle( 0,  0, QS, QS),
                          targetImage, new Rectangle(QS,  0, QS, QS));      // Black should be upper-right.
        assertPixelsEqual(sourceImage, new Rectangle(QS, QS, QS, QS),
                          targetImage, new Rectangle( 0, QS, QS, QS));      // Blue should be lower-left.
        assertPixelsEqual(sourceImage, new Rectangle(QS,  0, QS, QS),
                          targetImage, new Rectangle(QS, QS, QS, QS));      // Red should be lower-right.
    }

    /**
     * Tests an operation moving the dimension of temporal axis in a four-dimensional coverage.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testTemporalAxisMoved() throws TransformException {
        final GridCoverage source = createCoverageND(true);
        final GridGeometry target = createGridGeometryND(HardCodedCRS.WGS84_4D_TIME_FIRST, 1, 2, 3, 0, false);
        final GridCoverage result = resample(source, target);
        assertAxisDirectionsEqual(result.getGridGeometry().getCoordinateReferenceSystem().getCoordinateSystem(),
                new AxisDirection[] {AxisDirection.FUTURE, AxisDirection.EAST, AxisDirection.NORTH, AxisDirection.UP},
                "Expected (t,λ,φ,H) axes.");

        assertSampleValuesEqual(source.render(null), result.render(null), STRICT, null);
    }

    /**
     * Tests resampling in a sub-region specified by a grid extent. This method uses a three-dimensional coverage,
     * which implies that this method also tests the capability to identify which slice needs to be resampled.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testSubGridExtent() throws TransformException {
        final GridCoverage source     = createCoverageND(false);
        final GridGeometry sourceGeom = source.getGridGeometry();
        final GridGeometry targetGeom = new GridGeometry(
                new GridExtent(null, new long[] {LX+2, LY+2, gridZ},
                                     new long[] {LX+5, LY+5, gridZ}, true),
                CELL_CENTER, sourceGeom.gridToCRS,
                sourceGeom.getCoordinateReferenceSystem());

        final GridCoverage result = resample(source, targetGeom);
        assertEquals(targetGeom, result.getGridGeometry());
        /*
         * Verify that the target coverage contains all pixel values of the source coverage.
         * Iteration over source pixels needs to be restricted to the `targetGeom` extent.
         */
        final RenderedImage sourceImage = source.render(null);
        RenderedImage targetImage = result.render(null);
        assertPixelsEqual(sourceImage, new Rectangle(2, 2, 4, 4),
                          targetImage, null);
        /*
         * Verify GridCoverage.render(GridExtent) contract: the origin of the returned image
         * shall be the lower-left corner of `sliceExtent`, which is (3,3) in this test.
         */
        targetImage = result.render(new GridExtent(null,
                new long[] {LX+3, LY+3, gridZ},
                new long[] {LX+4, LY+4, gridZ}, true));
        assertPixelsEqual(sourceImage, new Rectangle(3, 3, 2, 2),
                          targetImage, new Rectangle(0, 0, 2, 2));
    }

    /**
     * Tests resampling in a sub-region specified by a grid extent spanning a single column.
     * When trying to optimize resampling by dropping dimensions, it can happen that transform dimensions
     * are reduced to 1D. However, it is a problem for image case which requires 2D coordinates.
     * So we must ensure that resample conversion keeps at least two dimensions.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testSubGridExtentColumnar() throws TransformException {
        final GridCoverage2D source   = createCoverage2D();
        final GridGeometry sourceGeom = source.getGridGeometry();
        final GridExtent sourceExtent = sourceGeom.getExtent();
        final GridExtent targetExtent = new GridExtent(null,
                new long[] {sourceExtent.getLow(0), sourceExtent.getLow (1)},
                new long[] {sourceExtent.getLow(0), sourceExtent.getHigh(1)}, true);
        final GridGeometry targetGeom = new GridGeometry(
                targetExtent, CELL_CENTER,
                sourceGeom.getGridToCRS(CELL_CENTER),
                sourceGeom.getCoordinateReferenceSystem());

        final GridCoverage result = resample(source, targetGeom);
        final int height = (int) targetExtent.getSize(1);
        assertPixelsEqual(source.render(null), new Rectangle(0, 0, 1, height), result.render(null), null);
    }

    /**
     * Tests resampling in a sub-region specified by an envelope.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testSubGeographicArea() throws TransformException {
        final GridCoverage2D source = createCoverage2D();             // Envelope2D(20, 15, 60, 62)
        final GridGeometry gg = new GridGeometry(null,
                new Envelope2D(HardCodedCRS.WGS84, 18, 20, 17, 31), GridOrientation.HOMOTHETY);
        final GridCoverage target = resample(source, gg);
        final GridExtent sourceExtent = source.getGridGeometry().getExtent();
        final GridExtent targetExtent = target.getGridGeometry().getExtent();
        assertTrue(sourceExtent.getSize(0) > targetExtent.getSize(0));
        assertTrue(sourceExtent.getSize(1) > targetExtent.getSize(1));
    }

    /**
     * Tests application of a non-linear transform.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testReprojection() throws TransformException {
        final GridCoverage2D source = createCoverage2D();
        GridGeometry gg = new GridGeometry(null, CELL_CENTER, null, HardCodedConversions.mercator());
        final GridCoverage target = resample(source, gg);
        assertTrue(target.getGridGeometry().getExtent().startsAtZero());
        /*
         * Mercator projection does not change pixel width, but change pixel height.
         */
        final GridExtent sourceExtent = source.getGridGeometry().getExtent();
        final GridExtent targetExtent = target.getGridGeometry().getExtent();
        assertEquals(sourceExtent.getSize(0),   targetExtent.getSize(0));
        assertTrue  (sourceExtent.getSize(1) <= targetExtent.getSize(1));
    }

    /**
     * Tests application of a three-dimensional transform which cannot be reduced to a two-dimensional transform.
     * It happens for example when transformation of <var>x</var> or <var>y</var> coordinate depends on <var>z</var>
     * coordinate value. In such case we cannot separate the 3D transform into (2D + 1D) transforms. This method
     * verifies that {@link ResampledGridCoverage} nevertheless manages to do its work even in that situation.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testNonSeparableGridToCRS() throws TransformException {
        final GridCoverage source = createCoverageND(false);
        final MatrixSIS nonSeparableMatrix = Matrices.createDiagonal(4, 4);
        nonSeparableMatrix.setElement(0, 2, 1);     // Make X dependent of Z.
        nonSeparableMatrix.setElement(1, 2, 1);     // Make Y dependent of Z.
        final MathTransform nonSeparableG2C = MathTransforms.concatenate(
                source.getGridGeometry().getGridToCRS(CELL_CENTER),
                MathTransforms.linear(nonSeparableMatrix));
        {
            /*
             * The test in this block is not a `ResampleGridCoverage` test, but rather a
             * check for a condition that we need for the test performed in this method.
             */
            final TransformSeparator separator = new TransformSeparator(nonSeparableG2C);
            separator.addSourceDimensions(0, 1);
            separator.addTargetDimensions(0, 1);
            assertNotNull(assertThrows(FactoryException.class, () -> separator.separate(),
                    "Test requires a non-separable transform, but separation succeed."));
        }
        final GridGeometry targetGeom = new GridGeometry(
                null,           // Let the resample operation compute the extent automatically.
                CELL_CENTER, nonSeparableG2C,
                source.getCoordinateReferenceSystem());
        /*
         * Real test is below (above code was only initialization).
         * Target image should be 6×6 pixels, like source image.
         */
        final GridCoverage result = resample(source, targetGeom);
        assertSampleValuesEqual(source.render(null), result.render(null), STRICT, null);
    }

    /**
     * Tests the addition of a temporal axis. The value to insert in the temporal coordinate can be computed
     * from the four-dimensional "grid to CRS" transform given in argument to the {@code resample(…)} method,
     * combined with the source grid extent.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testDimensionalityIncrease() throws TransformException {
        final GridCoverage source3D = createCoverageND(false);
        final GridGeometry target4D = createGridGeometryND(HardCodedCRS.WGS84_4D, 0, 1, 2, 3, false);
        final GridCoverage result   = resample(source3D, target4D);
        assertEquals(target4D, result.getGridGeometry());
        assertSampleValuesEqual(source3D.render(null), result.render(null), STRICT, null);
    }

    /**
     * Tests the removal of temporal axis.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testDimensionalityReduction() throws TransformException {
        final GridGeometry target3D = createGridGeometryND(HardCodedCRS.WGS84_3D, 0, 1, 2, 3, false);
        final GridCoverage source4D = createCoverageND(true);
        final GridCoverage result   = resample(source4D, target3D);
        assertEquals(target3D, result.getGridGeometry());
        assertSampleValuesEqual(source4D.render(null), result.render(null), STRICT, null);
    }

    /**
     * Tests resampling with a target domain larger than the source domain.
     * Pixel outside the source domain shall be set to fill value, which is 0.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     *
     * @see <a href="https://issues.apache.org/jira/browse/SIS-495">SIS-495</a>
     */
    @Test
    public void testDomainIncrease() throws TransformException {
        final int size = 2;
        final CoordinateReferenceSystem crs = HardCodedCRS.WGS84;
        final BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY);
        image.getRaster().setDataElements(0, 0, size, size, new byte[] {10, 12, 16, 14});
        final AffineTransform2D gridToCRS = new AffineTransform2D(1, 0, 0, -1, 0, 0);
        final GridGeometry sourceGrid = new GridGeometry(null, CELL_CENTER, gridToCRS, crs);
        final GridGeometry targetGrid = new GridGeometry(new GridExtent(4, 4), CELL_CENTER, gridToCRS, crs);
        final GridCoverage source     = new GridCoverage2D(sourceGrid, null, image);
        final GridCoverage target     = resample(source, targetGrid);
        assertValuesEqual(target.render(null), 0, new double[][] {
            {10, 12, 0, 0},
            {16, 14, 0, 0},
            { 0,  0, 0, 0},
            { 0,  0, 0, 0}
        });
    }

    /**
     * Tests resampling of an image associated to a coordinate system using the 0 to 360° range of longitude.
     * The image crosses the 180° longitude. The resampling does not involve map projection.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testLongitude360() throws TransformException {
        final int width = 32;
        final int height = 3;
        final GridGeometry source = new GridGeometry(
                new GridExtent(width, height), CELL_CENTER,
                new AffineTransform2D(1, 0, 0, -1, 164, 0),
                HardCodedCRS.WGS84.forConvention(AxesConvention.POSITIVE_RANGE));
        /*
         * Above grid extent is [164 … 195]° in longitude. The part that exceed 180° is equivalent to
         * a [-180 … -165]° range. The extent below requests only a part of it, namely [-173 … -167]°.
         * The first pixel of resampled image is the 23th pixel of original image.
         */
        final GridGeometry target = new GridGeometry(
                new GridExtent(7, height), CELL_CENTER,
                new AffineTransform2D(1, 0, 0, -1, -173, 0),
                HardCodedCRS.WGS84);

        final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
        image.getRaster().setPixels(0, 0, width, height, IntStream.range(100, 100 + width*height).toArray());
        final GridCoverage2D coverage = new GridCoverage2D(source, null, image);
        final GridCoverage resampled = resample(coverage, target);
        assertValuesEqual(resampled.render(null), 0, new double[][] {
            {123, 124, 125, 126, 127, 128, 129},
            {155, 156, 157, 158, 159, 160, 161},
            {187, 188, 189, 190, 191, 192, 193}
        });
    }

    /**
     * Tests map reprojection of an image associated to a coordinate system using the 0 to 360° range of longitude.
     *
     * @throws TransformException if some coordinates cannot be transformed to the target grid geometry.
     */
    @Test
    public void testReprojectionFromLongitude360() throws TransformException {
        /*
         * Longitudes from 91°E to 235°E (in WGS84 geographic CRS), which is equivalent to 91°E to 125°W.
         * Latitude range is not important for this test.
         */
        final int width  = 8;
        final int height = 5;
        final GridGeometry source = new GridGeometry(
                new GridExtent(null, null, new long[] {width, height}, false), CELL_CENTER,
                new AffineTransform2D(18, 0, 0, 19, 100, -20),
                HardCodedCRS.WGS84.forConvention(AxesConvention.POSITIVE_RANGE));
        /*
         * 180°W to 180″E (the world) and 80°S to 80°N in Mercator projection.
         * Latitude range is about the same as source grid geometry.
         */
        final double xmin = -2.0037508342789244E7;
        final GridGeometry target = new GridGeometry(
                new GridExtent(null, null, new long[] {2*width, height}, false), CELL_CENTER,
                new AffineTransform2D(-xmin/width, 0, 0, 2610000, xmin, -2376500),
                HardCodedConversions.mercator());
        /*
         * Resample the image by specifying fully the target grid geometry.
         * The grid coverage should have the exact same instance.
         */
        final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
        image.getRaster().setPixels(0, 0, width, height, IntStream.range(100, 100 + width*height).toArray());
        final GridCoverage2D coverage = new GridCoverage2D(source, null, image);
        final GridCoverage resampled = resample(coverage, target);
        assertSame(target, resampled.getGridGeometry());
        /*
         * Sample values 100, 101, 102, … should be distributed on both sides of the image.
         */
        assertValuesEqual(resampled.render(null), 0, new double[][] {
            {104, 106, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 102, 103},
            {112, 114, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111},
            {120, 122, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 118, 119},
            {128, 130, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 126, 127},
            {136, 138, 139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 134, 135},
        });
    }

    /**
     * Returns an image with only the queries part of the given image.
     * This is an helper tools which can be invoked during debugging
     * session in IDE capable to display images.
     *
     * <h4>Usage</h4>
     * Add a new watch calling this method on wanted image.
     *
     * <h4>Limitations</h4>
     * <ul>
     *   <li>If given image color-model is null, this method assumes 3 byte/RGB image.</li>
     *   <li>Works only with single-tile images.</li>
     * </ul>
     *
     * @param source  the image to display.
     * @param extent  if non-null, crop rendering to the rectangle defined by given extent,
     *                assuming extent low coordinate matches source image (0,0) coordinate.
     * @return the image directly displayable through debugger.
     */
    private static BufferedImage debug(final RenderedImage source, final GridExtent extent) {
        Raster tile = source.getTile(source.getMinTileX(), source.getMinTileY());
        final int width, height;
        if (extent == null) {
            tile   = tile.createTranslatedChild(0, 0);
            width  = tile.getWidth();
            height = tile.getHeight();
        } else {
            width  = StrictMath.toIntExact(extent.getSize(0));
            height = StrictMath.toIntExact(extent.getSize(1));
            tile   = tile.createChild(0, 0, width, height, 0, 0, null);
        }
        final BufferedImage view;
        if (source.getColorModel() == null) {
            view = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            view.getRaster().setRect(tile);
        } else {
            final WritableRaster wr = tile.createCompatibleWritableRaster(0, 0, width, height);
            wr.setRect(tile);
            view = new BufferedImage(source.getColorModel(), wr, false, null);
        }
        return view;
    }
}
