/*
 * 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.Map;
import java.util.Arrays;
import java.awt.geom.Path2D;
import org.apache.sis.internal.feature.j2d.PathBuilder;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.Debug;


/**
 * Coordinates of a polyline under construction. Coordinates can be appended in only one direction.
 * If the polyline may growth on both directions (which happens if the polyline crosses the bottom
 * side and the right side of a cell), then the two directions are handled by two distinct instances
 * connected by their {@link #opposite} field.
 *
 * <p>When a polyline has been completed, its content is copied to {@link Tracer.Level#path}
 * and the {@code PolylineBuffer} object is recycled for a new polyline.</p>
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.3
 * @since   1.1
 * @module
 */
final class PolylineBuffer {
    /**
     * Number of coordinates in a tuple.
     */
    static final int DIMENSION = 2;

    /**
     * Coordinates as (x,y) tuples. This array is expanded as needed.
     */
    double[] coordinates;

    /**
     * Number of valid elements in the {@link #coordinates} array.
     * This is twice the number of points.
     */
    int size;

    /**
     * If the polyline has points added to its two extremities, the other extremity. Otherwise {@code null}.
     * The first point of {@code opposite} polyline is connected to the first point of this polyline.
     * Consequently when those two polylines are joined in a single polyline, the coordinates of either
     * {@code this} or {@code opposite} must be iterated in reverse order.
     */
    PolylineBuffer opposite;

    /**
     * Creates an initially empty polyline.
     */
    PolylineBuffer() {
        coordinates = ArraysExt.EMPTY_DOUBLE;
    }

    /**
     * Creates a new polyline wrapping the given coordinates. Used for wrapping {@link Fragments}
     * instances in objects expected by {@link Tracer#writeTo(Joiner, Polyline[], boolean)}.
     * Those {@code Polyline} instances are temporary.
     */
    PolylineBuffer(final double[] data) {
        coordinates = data;
        size = data.length;
    }

    /**
     * Discards all coordinates in this polyline. This method does not clear
     * the {@link #opposite} polyline; it is caller's responsibility to do so.
     */
    final void clear() {
        opposite = null;
        size = 0;
    }

    /**
     * Returns whether this polyline is empty. This method is used only for {@code assert isEmpty()}
     * statement because of the check for {@code opposite == null}: an empty polyline should not have
     * a non-null {@link #opposite} value.
     */
    final boolean isEmpty() {
        return size == 0 & (opposite == null);
    }

    /**
     * Declares that the specified polyline will add points in the direction opposite to this polyline.
     * This happens when the polyline crosses the bottom side and the right side of a cell (assuming an
     * iteration from left to right and top to bottom).
     *
     * <p>This method is typically invoked in the following pattern (but this is not mandatory).
     * An important aspect is that {@code this} and {@code other} should be on perpendicular axes:</p>
     *
     * {@preformat java
     *     interpolateOnBottomSide(polylinesOnTop[x].attach(polylineOnLeft));
     * }
     *
     * @return {@code this} for method calls chaining.
     */
    final PolylineBuffer attach(final PolylineBuffer other) {
        assert (opposite == null) & (other.opposite == null);
        other.opposite = this;
        opposite = other;
        return this;
    }

    /**
     * Transfers all coordinates from given polylines to this polylines, in same order.
     * This is used when polyline on the left side continues on bottom side,
     * or conversely when polyline on the top side continues on right side.
     * This polyline shall be empty before this method is invoked.
     * The given source will become empty after this method returned.
     *
     * @param  source  the source from which to take data.
     * @return {@code this} for method calls chaining.
     */
    final PolylineBuffer transferFrom(final PolylineBuffer source) {
        assert isEmpty();
        final double[] swap = coordinates;
        coordinates = source.coordinates;
        size        = source.size;
        opposite    = source.opposite;
        if (opposite != null) {
            opposite.opposite = this;
        }
        source.clear();
        source.coordinates = swap;
        return this;
    }

    /**
     * Transfers all coordinates from this polyline to the polyline going in opposite direction.
     * This is used when this polyline reached the right image border, in which case its data
     * will be lost if we do not copy them somewhere.
     *
     * @return {@code true} if coordinates have been transferred,
     *         or {@code false} if there is no opposite direction.
     */
    final boolean transferToOpposite() {
        if (opposite == null) {
            return false;
        }
        final int sum = size + opposite.size;
        double[] data = opposite.coordinates;
        if (sum > data.length) {
            data = new double[sum];
        }
        System.arraycopy(opposite.coordinates, 0, data, size, opposite.size);
        for (int i=0, t=size; (t -= DIMENSION) >= 0;) {
            data[t  ] = coordinates[i++];
            data[t+1] = coordinates[i++];
        }
        opposite.size = sum;
        opposite.coordinates = data;
        opposite.opposite = null;
        clear();
        return true;
    }

    /**
     * Appends given coordinates to this polyline.
     *
     * @param  x  first coordinate of the (x,y) tuple to add.
     * @param  y  second coordinate of the (x,y) tuple to add.
     */
    final void append(final double x, final double y) {
        if (size >= coordinates.length) {
            coordinates = Arrays.copyOf(coordinates, Math.max(Math.multiplyExact(size, 2), 32));
        }
        coordinates[size++] = x;
        coordinates[size++] = y;
    }

    /**
     * Returns a string representation of this {@code Polyline} for debugging purposes.
     */
    @Override
    public String toString() {
        return PathBuilder.toString(coordinates, size);
    }

    /**
     * Appends the pixel coordinates of this polyline to the given path, 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.
     *
     * @param  appendTo  where to append the coordinates.
     *
     * @see Tracer.Level#toRawPath(Map)
     */
    @Debug
    final void toRawPath(final Map<PolylineStage,Path2D> appendTo) {
        int i = 0;
        if (i < size) {
            final Path2D p = PolylineStage.BUFFER.destination(appendTo);
            p.moveTo(coordinates[i++], coordinates[i++]);
            while (i < size) {
                p.lineTo(coordinates[i++], coordinates[i++]);
            }
        }
    }
}
