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

import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Line2D;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.AffineTransform;
import java.awt.geom.IllegalPathStateException;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform2D;
import org.opengis.referencing.operation.TransformException;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.apache.sis.internal.referencing.Resources;
import org.apache.sis.internal.referencing.j2d.ShapeUtilities;


/**
 * Base class for math transforms that are known to be two-dimensional in all cases.
 * Two-dimensional math transforms are not required to extend this class,
 * however doing so may simplify their implementation.
 *
 * <p>The simplest way to implement this abstract class is to provide an implementation for the following methods
 * only:</p>
 * <ul>
 *   <li>{@link #transform(double[], int, double[], int, boolean)}</li>
 * </ul>
 *
 * However more performance may be gained by overriding the other {@code transform} methods as well.
 *
 * <div class="section">Immutability and thread safety</div>
 * All Apache SIS implementations of {@code MathTransform2D} are immutable and thread-safe.
 * It is highly recommended that third-party implementations be immutable and thread-safe too.
 * This means that unless otherwise noted in the javadoc, {@code MathTransform2D} instances can
 * be shared by many objects and passed between threads without synchronization.
 *
 * <div class="section">Serialization</div>
 * {@code MathTransform2D} may or may not be serializable, at implementation choices.
 * Most Apache SIS implementations are serializable, but the serialized objects are not guaranteed to be compatible
 * with future SIS versions. Serialization should be used only for short term storage or RMI between applications
 * running the same SIS version.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.5
 * @since   0.5
 * @module
 */
public abstract class AbstractMathTransform2D extends AbstractMathTransform implements MathTransform2D {
    /**
     * Constructor for subclasses.
     */
    protected AbstractMathTransform2D() {
    }

    /**
     * Returns the dimension of input points, which is always 2.
     */
    @Override
    public final int getSourceDimensions() {
        return 2;
    }

    /**
     * Returns the dimension of output points, which is always 2.
     */
    @Override
    public final int getTargetDimensions() {
        return 2;
    }

    /**
     * Transforms the specified {@code ptSrc} and stores the result in {@code ptDst}.
     * The default implementation invokes {@link #transform(double[], int, double[], int, boolean)}
     * using a temporary array of doubles.
     *
     * @param  ptSrc  the coordinate point to be transformed.
     * @param  ptDst  the coordinate point that stores the result of transforming {@code ptSrc},
     *                or {@code null} if a new point shall be created.
     * @return the coordinate point after transforming {@code ptSrc} and storing the result in {@code ptDst},
     *         or in a new point if {@code ptDst} was null.
     * @throws TransformException if the point can not be transformed.
     *
     * @see MathTransform2D#transform(Point2D, Point2D)
     */
    @Override
    public Point2D transform(final Point2D ptSrc, final Point2D ptDst) throws TransformException {
        return transform(this, ptSrc, ptDst);
    }

    /**
     * Implementation of {@link #transform(Point2D, Point2D)} shared by the inverse transform.
     */
    static Point2D transform(final AbstractMathTransform tr, final Point2D ptSrc, final Point2D ptDst) throws TransformException {
        final double[] ord = new double[] {ptSrc.getX(), ptSrc.getY()};
        tr.transform(ord, 0, ord, 0, false);
        if (ptDst != null) {
            ptDst.setLocation(ord[0], ord[1]);
            return ptDst;
        } else {
            return new Point2D.Double(ord[0], ord[1]);
        }
    }

    /**
     * Transforms the specified shape. The default implementation computes quadratic curves
     * using three points for each line segment in the shape. The returned object is often
     * a {@link Path2D}, but may also be a {@link Line2D} or a {@link QuadCurve2D} if such
     * simplification is possible.
     *
     * @param  shape  shape to transform.
     * @return transformed shape, or {@code shape} if this transform is the identity transform.
     * @throws TransformException if a transform failed.
     */
    @Override
    public Shape createTransformedShape(final Shape shape) throws TransformException {
        return isIdentity() ? shape : createTransformedShape(this, shape, null, null, false);
    }

    /**
     * Transforms a geometric shape. This method always copy transformed coordinates in a new object.
     * The new object is often a {@link Path2D}, but may also be a {@link Line2D} or a {@link QuadCurve2D}
     * if such simplification is possible.
     *
     * @param  mt             the math transform to use.
     * @param  shape          the geometric shape to transform.
     * @param  preTransform   an optional affine transform to apply <em>before</em> the
     *                        transformation using {@code this}, or {@code null} if none.
     * @param  postTransform  an optional affine transform to apply <em>after</em> the transformation
     *                        using {@code this}, or {@code null} if none.
     * @param  horizontal     {@code true} for forcing parabolic equation.
     * @return the transformed geometric shape.
     * @throws TransformException if a transformation failed.
     */
    static Shape createTransformedShape(final MathTransform2D mt,
                                        final Shape           shape,
                                        final AffineTransform preTransform,
                                        final AffineTransform postTransform,
                                        final boolean         horizontal)
            throws TransformException
    {
        final PathIterator    it = shape.getPathIterator(preTransform);
        final Path2D.Double path = new Path2D.Double(it.getWindingRule());
        final double[]    buffer = new double[6];
        double ax=0, ay=0;                                  // Coordinate of the last point before transform.
        double px=0, py=0;                                  // Coordinate of the last point after  transform.
        for (; !it.isDone(); it.next()) {
            switch (it.currentSegment(buffer)) {
                default: {
                    throw new IllegalPathStateException();
                }
                case PathIterator.SEG_CLOSE: {
                    /*
                     * Close the geometric shape and continues the loop. We use the 'continue' instruction
                     * here instead of 'break' because we do not want to execute the code after the switch
                     * (addition of transformed points into the path - there is no such point in a SEG_CLOSE).
                     */
                    path.closePath();
                    continue;
                }
                case PathIterator.SEG_MOVETO: {
                    /*
                     * Transform the single point and adds it to the path. We use the 'continue' instruction
                     * here instead of 'break' because we do not want to execute the code after the switch
                     * (addition of a line or a curve - there is no such curve to add here; we are just moving
                     * the cursor).
                     */
                    ax = buffer[0];
                    ay = buffer[1];
                    mt.transform(buffer, 0, buffer, 0, 1);
                    px = buffer[0];
                    py = buffer[1];
                    if (Double.isFinite(px) && Double.isFinite(py)) {
                        path.moveTo(px, py);
                        continue;
                    } else {
                        throw new TransformException(Resources.format(Resources.Keys.CanNotTransformCoordinates_2, ax, ay));
                    }
                }
                case PathIterator.SEG_LINETO: {
                    /*
                     * Insert a new control point at 'buffer[0,1]'. This control point will
                     * be initialised with coordinates in the middle of the straight line:
                     *
                     *  x = 0.5 * (x1+x2)
                     *  y = 0.5 * (y1+y2)
                     *
                     * This point will be transformed after the 'switch', which is why we use
                     * the 'break' statement here instead of 'continue' as in previous case.
                     */
                    buffer[0] = 0.5 * (ax + (ax = buffer[0]));
                    buffer[1] = 0.5 * (ay + (ay = buffer[1]));
                    buffer[2] = ax;
                    buffer[3] = ay;
                    break;
                }
                case PathIterator.SEG_QUADTO: {
                    /*
                     * Replace the control point in 'buffer[0,1]' by a new control point lying on the quadratic curve.
                     * Coordinates for a point in the middle of the curve can be computed with:
                     *
                     *  x = 0.5 * (ctrlx + 0.5 * (x1+x2))
                     *  y = 0.5 * (ctrly + 0.5 * (y1+y2))
                     *
                     * There is no need to keep the old control point because it was not lying on the curve.
                     */
                    buffer[0] = 0.5 * (buffer[0] + 0.5*(ax + (ax = buffer[2])));
                    buffer[1] = 0.5 * (buffer[1] + 0.5*(ay + (ay = buffer[3])));
                    break;
                }
                case PathIterator.SEG_CUBICTO: {
                    /*
                     * Replace the control point in 'buffer[0,1]' by a new control point lying on the cubic curve.
                     * Coordinates for a point in the middle of the curve can be computed with:
                     *
                     *  x = 0.25 * (1.5 * (ctrlx1 + ctrlx2) + 0.5 * (x1 + x2));
                     *  y = 0.25 * (1.5 * (ctrly1 + ctrly2) + 0.5 * (y1 + y2));
                     *
                     * There is no need to keep the old control point because it was not lying on the curve.
                     *
                     * NOTE: The computed point is on the curve, but may not be representative of the shape.
                     *       This algorithm replaces two control points by a single one, because we did not
                     *       venture into a more sophisticated algorithm producing a CubicCurve2D. For now,
                     *       we presume that the current algorithm is okay if the curve is smooth enough.
                     */
                    buffer[0] = 0.25 * (1.5 * (buffer[0] + buffer[2]) + 0.5 * (ax + (ax = buffer[4])));
                    buffer[1] = 0.25 * (1.5 * (buffer[1] + buffer[3]) + 0.5 * (ay + (ay = buffer[5])));
                    buffer[2] = ax;
                    buffer[3] = ay;
                    break;
                }
            }
            /*
             * Apply the transform on the point in the buffer, and append the transformed points
             * to the general path. Try to add them as a quadratic line, or as a straight line if
             * the computed control point is colinear with the starting and ending points.
             */
            mt.transform(buffer, 0, buffer, 0, 2);
            final Point2D ctrlPoint = ShapeUtilities.parabolicControlPoint(px, py,
                    buffer[0], buffer[1],
                    buffer[2], buffer[3],
                    horizontal);
            px = buffer[2];
            py = buffer[3];
            if (Double.isFinite(px) && Double.isFinite(py)) {
                if (ctrlPoint == null) {
                    path.lineTo(px, py);
                } else {
                    final double cx = ctrlPoint.getX();
                    final double cy = ctrlPoint.getY();
                    if (Double.isFinite(cx) && Double.isFinite(cy)) {
                        path.quadTo(cx, cy, px, py);
                    } else {
                        throw new TransformException(Resources.format(Resources.Keys.CanNotTransformGeometry));
                    }
                }
            } else {
                throw new TransformException(Resources.format(Resources.Keys.CanNotTransformCoordinates_2, ax, ay));
            }
        }
        /*
         * Shape transformation is done. Apply an affine transform if it was requested,
         * then simplify the geometric object (not the coordinate values) if possible.
         */
        if (postTransform != null) {
            path.transform(postTransform);
        }
        return ShapeUtilities.toPrimitive(path);
    }

    /**
     * Gets the derivative of this transform at a point.
     * The default implementation performs the following steps:
     *
     * <ul>
     *   <li>Copy the coordinate in a temporary array and pass that array to the
     *       {@link #transform(double[], int, double[], int, boolean)} method,
     *       with the {@code derivate} boolean argument set to {@code true}.</li>
     *   <li>If the later method returned a non-null matrix, returns that matrix.
     *       Otherwise throws {@link TransformException}.</li>
     * </ul>
     *
     * @param  point  the coordinate point where to evaluate the derivative.
     * @return the derivative at the specified point as a 2×2 matrix.
     * @throws TransformException if the derivative can not be evaluated at the specified point.
     */
    @Override
    public Matrix derivative(final Point2D point) throws TransformException {
        return derivative(this, point);
    }

    /**
     * Implementation of {@link #derivative(DirectPosition)} shared by the inverse transform.
     */
    static Matrix derivative(final AbstractMathTransform tr, final Point2D point) throws TransformException {
        final double[] coordinate = new double[] {point.getX(), point.getY()};
        final Matrix derivative = tr.transform(coordinate, 0, null, 0, true);
        if (derivative == null) {
            throw new TransformException(Resources.format(Resources.Keys.CanNotComputeDerivative));
        }
        return derivative;
    }

    /**
     * Returns the inverse transform of this object.
     * The default implementation returns {@code this} if this transform is an identity transform,
     * or throws an exception otherwise. Subclasses should override this method.
     */
    @Override
    public MathTransform2D inverse() throws NoninvertibleTransformException {
        return (MathTransform2D) super.inverse();
    }

    /**
     * Base class for implementation of inverse math transforms.
     * This inner class is the inverse of the enclosing {@link AbstractMathTransform2D}.
     *
     * <div class="section">Serialization</div>
     * This object may or may not be serializable, at implementation choices.
     * Most Apache SIS implementations are serializable, but the serialized objects are not guaranteed to be compatible
     * with future SIS versions. Serialization should be used only for short term storage or RMI between applications
     * running the same SIS version.
     *
     * @author  Martin Desruisseaux (Geomatys)
     * @version 1.0
     * @since   0.5
     * @module
     */
    protected abstract static class Inverse extends AbstractMathTransform.Inverse implements MathTransform2D {
        /**
         * Constructs an inverse math transform.
         */
        protected Inverse() {
        }

        /**
         * Returns the inverse of this math transform.
         * The returned transform should be the enclosing math transform.
         */
        @Override
        public abstract MathTransform2D inverse();

        /**
         * Transforms the specified {@code ptSrc} and stores the result in {@code ptDst}.
         * The default implementation invokes {@link #transform(double[], int, double[], int, boolean)}
         * using a temporary array of doubles.
         *
         * @param  ptSrc  the coordinate point to be transformed.
         * @param  ptDst  the coordinate point that stores the result of transforming {@code ptSrc},
         *                or {@code null} if a new point shall be created.
         * @return the coordinate point after transforming {@code ptSrc} and storing the result in {@code ptDst},
         *         or in a new point if {@code ptDst} was null.
         * @throws TransformException if the point can not be transformed.
         *
         * @see MathTransform2D#transform(Point2D, Point2D)
         */
        @Override
        public Point2D transform(final Point2D ptSrc, final Point2D ptDst) throws TransformException {
            return AbstractMathTransform2D.transform(this, ptSrc, ptDst);
        }

        /**
         * Transforms the specified shape. The default implementation computes quadratic curves
         * using three points for each line segment in the shape. The returned object is often
         * a {@link Path2D}, but may also be a {@link Line2D} or a {@link QuadCurve2D} if such
         * simplification is possible.
         *
         * @param  shape  shape to transform.
         * @return transformed shape, or {@code shape} if this transform is the identity transform.
         * @throws TransformException if a transform failed.
         */
        @Override
        public Shape createTransformedShape(final Shape shape) throws TransformException {
            return isIdentity() ? shape : AbstractMathTransform2D.createTransformedShape(this, shape, null, null, false);
        }

        /**
         * Gets the derivative of this transform at a point.
         * The default implementation performs the following steps:
         *
         * <ul>
         *   <li>Copy the coordinate in a temporary array and pass that array to the
         *       {@link #transform(double[], int, double[], int, boolean)} method,
         *       with the {@code derivate} boolean argument set to {@code true}.</li>
         *   <li>If the later method returned a non-null matrix, returns that matrix.
         *       Otherwise throws {@link TransformException}.</li>
         * </ul>
         *
         * @param  point  the coordinate point where to evaluate the derivative.
         * @return the derivative at the specified point as a 2×2 matrix.
         * @throws TransformException if the derivative can not be evaluated at the specified point.
         */
        @Override
        public Matrix derivative(final Point2D point) throws TransformException {
            return AbstractMathTransform2D.derivative(this, point);
        }
    }
}
