/*
 * 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 java.io.Serializable;

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>, Serializable {

    /** 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);

    /** Serializable UID */
    private static final long serialVersionUID = 20190224L;

    /** 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));
    }
}
