/*
 * 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.commons.geometry.core.partition.test;

import org.apache.commons.geometry.core.Transform;
import org.apache.commons.geometry.core.partitioning.EmbeddingHyperplane;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
import org.apache.commons.geometry.core.partitioning.HyperplaneLocation;

/** Class representing a line in two dimensional Euclidean space. This
 * class should only be used for testing purposes.
 */
public class TestLine implements EmbeddingHyperplane<TestPoint2D, TestPoint1D> {

    /** Line pointing along the positive x-axis. */
    public static final TestLine X_AXIS = new TestLine(0, 0, 1, 0);

    /** Line pointing along the positive y-axis. */
    public static final TestLine Y_AXIS = new TestLine(0, 0, 0, 1);

    /** X value of the normalized line direction. */
    private final double directionX;

    /** Y value of the normalized line direction. */
    private final double directionY;

    /** The distance between the origin and the line. */
    private final double originOffset;

    /** Construct a line from two points. The line points in the direction from
     * {@code p1} to {@code p2}.
     * @param p1 first point
     * @param p2 second point
     */
    public TestLine(final TestPoint2D p1, final TestPoint2D p2) {
        this(p1.getX(), p1.getY(), p2.getX(), p2.getY());
    }

    /** Construct a line from two point, given by their components.
     * @param x1 x coordinate of first point
     * @param y1 y coordinate of first point
     * @param x2 x coordinate of second point
     * @param y2 y coordinate of second point
     */
    public TestLine(final double x1, final double y1, final double x2, final double y2) {
        double vecX = x2 - x1;
        double vecY = y2 - y1;

        double norm = norm(vecX, vecY);

        vecX /= norm;
        vecY /= norm;

        if (!Double.isFinite(vecX) || !Double.isFinite(vecY)) {
            throw new IllegalStateException("Unable to create line between points: (" +
                    x1 + ", " + y1 + "), (" + x2 + ", " + y2 + ")");
        }

        this.directionX = vecX;
        this.directionY = vecY;

        this.originOffset = signedArea(vecX, vecY, x1, y1);
    }

    /** Get the line origin, meaning the projection of the 2D origin onto the line.
     * @return line origin
     */
    public TestPoint2D getOrigin() {
        return toSpace(0);
    }

    /** Get the x component of the line direction.
     * @return x component of the line direction.
     */
    public double getDirectionX() {
        return directionX;
    }

    /** Get the y component of the line direction.
     * @return y component of the line direction.
     */
    public double getDirectionY() {
        return directionY;
    }

    /** {@inheritDoc} */
    @Override
    public double offset(TestPoint2D point) {
        return originOffset - signedArea(directionX, directionY, point.getX(), point.getY());
    }

    /** {@inheritDoc} */
    @Override
    public HyperplaneLocation classify(TestPoint2D point) {
        final double offset = offset(point);
        final double cmp = PartitionTestUtils.PRECISION.compare(offset, 0.0);
        if (cmp == 0) {
            return HyperplaneLocation.ON;
        }
        return cmp < 0 ? HyperplaneLocation.MINUS : HyperplaneLocation.PLUS;
    }

    /** {@inheritDoc} */
    @Override
    public boolean contains(TestPoint2D point) {
        return classify(point) == HyperplaneLocation.ON;
    }

    /** Get the location of the given 2D point in the 1D space of the line.
     * @param point point to project into the line's 1D space
     * @return location of the point in the line's 1D space
     */
    public double toSubspaceValue(TestPoint2D point) {
        return (directionX * point.getX()) + (directionY * point.getY());
    }

    /** {@inheritDoc} */
    @Override
    public TestPoint1D toSubspace(TestPoint2D point) {
        return new TestPoint1D(toSubspaceValue(point));
    }

    /** Get the 2D location of the given 1D location in the line's 1D space.
     * @param abscissa location in the line's 1D space.
     * @return the location of the given 1D point in 2D space
     */
    public TestPoint2D toSpace(final double abscissa) {
        if (Double.isInfinite(abscissa)) {
            int dirXCmp = PartitionTestUtils.PRECISION.sign(directionX);
            int dirYCmp = PartitionTestUtils.PRECISION.sign(directionY);

            double x;
            if (dirXCmp == 0) {
                // vertical line
                x = getOrigin().getX();
            }
            else {
                x = (dirXCmp < 0 ^ abscissa < 0) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
            }

            double y;
            if (dirYCmp == 0) {
                // horizontal line
                y = getOrigin().getY();
            }
            else {
                y = (dirYCmp < 0 ^ abscissa < 0) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
            }

            return new TestPoint2D(x, y);
        }

        final double ptX = (abscissa * directionX) + (-originOffset * directionY);
        final double ptY = (abscissa * directionY) + (originOffset * directionX);

        return new TestPoint2D(ptX, ptY);
    }

    /** {@inheritDoc} */
    @Override
    public TestPoint2D toSpace(TestPoint1D point) {
        return toSpace(point.getX());
    }

    /** {@inheritDoc} */
    @Override
    public TestPoint2D project(final TestPoint2D point) {
        return toSpace(toSubspaceValue(point));
    }

    /** {@inheritDoc} */
    @Override
    public TestLine reverse() {
        TestPoint2D pt = getOrigin();
        return new TestLine(pt.getX(), pt.getY(), pt.getX() - directionX, pt.getY() - directionY);
    }

    /** {@inheritDoc} */
    @Override
    public TestLine transform(Transform<TestPoint2D> transform) {
        TestPoint2D p1 = transform.apply(toSpace(0));
        TestPoint2D p2 = transform.apply(toSpace(1));

        return new TestLine(p1, p2);
    }

    /** {@inheritDoc} */
    @Override
    public boolean similarOrientation(Hyperplane<TestPoint2D> other) {
        final TestLine otherLine = (TestLine) other;
        final double dot = (directionX * otherLine.directionX) + (directionY * otherLine.directionY);
        return dot >= 0.0;
    }

    /** {@inheritDoc} */
    @Override
    public TestLineSegment span() {
        return new TestLineSegment(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, this);
    }

    /** Get the intersection point of the instance and another line.
     * @param other other line
     * @return intersection point of the instance and the other line
     *      or null if there is no unique intersection point (ie, the lines
     *      are parallel or coincident)
     */
    public TestPoint2D intersection(final TestLine other) {
        final double area = signedArea(directionX, directionY, other.directionX, other.directionY);
        if (PartitionTestUtils.PRECISION.eqZero(area)) {
            // lines are parallel
            return null;
        }

        final double x = ((other.directionX * originOffset) +
                (-directionX * other.originOffset)) / area;

        final double y = ((other.directionY * originOffset) +
                (-directionY * other.originOffset)) / area;

        return new TestPoint2D(x, y);
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append(this.getClass().getSimpleName())
            .append("[origin= ")
            .append(getOrigin())
            .append(", direction= (")
            .append(directionX)
            .append(", ")
            .append(directionY)
            .append(")]");

        return sb.toString();
    }

    /** Compute the signed area of the parallelogram with sides defined by the given
     * vectors.
     * @param x1 x coordinate of first vector
     * @param y1 y coordinate of first vector
     * @param x2 x coordinate of second vector
     * @param y2 y coordinate of second vector
     * @return the signed are of the parallelogram with side defined by the given
     *      vectors
     */
    private static double signedArea(final double x1, final double y1,
            final double x2, final double y2) {
        return (x1 * y2) + (-y1 * x2);
    }

    /** Compute the Euclidean norm.
     * @param x x coordinate value
     * @param y y coordinate value
     * @return Euclidean norm
     */
    public static double norm(final double x, final double y) {
        return Math.sqrt((x * x) + (y * y));
    }
}
