/*
 * 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.euclidean.twod;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.geometry.core.exception.GeometryValueException;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
import org.apache.commons.geometry.core.partitioning.Split;
import org.apache.commons.geometry.core.partitioning.bsp.AbstractBSPTree;
import org.apache.commons.geometry.core.partitioning.bsp.AbstractRegionBSPTree;
import org.apache.commons.geometry.core.precision.DoublePrecisionContext;

/** Binary space partitioning (BSP) tree representing a region in two dimensional
 * Euclidean space.
 */
public final class RegionBSPTree2D extends AbstractRegionBSPTree<Vector2D, RegionBSPTree2D.RegionNode2D> {
    /** List of line segment paths comprising the region boundary. */
    private List<Polyline> boundaryPaths;

    /** Create a new, empty region.
     */
    public RegionBSPTree2D() {
        this(false);
    }

    /** Create a new region. If {@code full} is true, then the region will
     * represent the entire 2D space. Otherwise, it will be empty.
     * @param full whether or not the region should contain the entire
     *      2D space or be empty
     */
    public RegionBSPTree2D(boolean full) {
        super(full);
    }

    /** Return a deep copy of this instance.
     * @return a deep copy of this instance.
     * @see #copy(org.apache.commons.geometry.core.partitioning.bsp.BSPTree)
     */
    public RegionBSPTree2D copy() {
        RegionBSPTree2D result = RegionBSPTree2D.empty();
        result.copy(this);

        return result;
    }

    /** {@inheritDoc} */
    @Override
    public Iterable<Segment> boundaries() {
        return createBoundaryIterable(b -> (Segment) b);
    }

    /** {@inheritDoc} */
    @Override
    public List<Segment> getBoundaries() {
        return createBoundaryList(b -> (Segment) b);
    }

    /** Get the boundary of the region as a list of connected line segment paths. The
     * line segments are oriented such that their minus (left) side lies on the
     * interior of the region.
     * @return line segment paths representing the region boundary
     */
    public List<Polyline> getBoundaryPaths() {
        if (boundaryPaths == null) {
            boundaryPaths = Collections.unmodifiableList(computeBoundaryPaths());
        }
        return boundaryPaths;
    }

    /** Add a convex area to this region. The resulting region will be the
     * union of the convex area and the region represented by this instance.
     * @param area the convex area to add
     */
    public void add(final ConvexArea area) {
        union(from(area));
    }

    /** Return a list of {@link ConvexArea}s representing the same region
     * as this instance. One convex area is returned for each interior leaf
     * node in the tree.
     * @return a list of convex areas representing the same region as this
     *      instance
     */
    public List<ConvexArea> toConvex() {
        final List<ConvexArea> result = new ArrayList<>();

        toConvexRecursive(getRoot(), ConvexArea.full(), result);

        return result;
    }

    /** Recursive method to compute the convex areas of all inside leaf nodes in the subtree rooted at the given
     * node. The computed convex areas are added to the given list.
     * @param node root of the subtree to compute the convex areas for
     * @param nodeArea the convex area for the current node; this will be split by the node's cut hyperplane to
     *      form the convex areas for any child nodes
     * @param result list containing the results of the computation
     */
    private void toConvexRecursive(final RegionNode2D node, final ConvexArea nodeArea, final List<ConvexArea> result) {
        if (node.isLeaf()) {
            // base case; only add to the result list if the node is inside
            if (node.isInside()) {
                result.add(nodeArea);
            }
        } else {
            // recurse
            Split<ConvexArea> split = nodeArea.split(node.getCutHyperplane());

            toConvexRecursive(node.getMinus(), split.getMinus(), result);
            toConvexRecursive(node.getPlus(), split.getPlus(), result);
        }
    }

    /** {@inheritDoc} */
    @Override
    public Split<RegionBSPTree2D> split(final Hyperplane<Vector2D> splitter) {
        return split(splitter, RegionBSPTree2D.empty(), RegionBSPTree2D.empty());
    }

    /** {@inheritDoc} */
    @Override
    public Vector2D project(final Vector2D pt) {
        // use our custom projector so that we can disambiguate points that are
        // actually equidistant from the target point
        final BoundaryProjector2D projector = new BoundaryProjector2D(pt);
        accept(projector);

        return projector.getProjected();
    }

    /** Compute the line segment paths comprising the region boundary.
     * @return the line segment paths comprising the region boundary
     */
    private List<Polyline> computeBoundaryPaths() {
        final InteriorAngleSegmentConnector connector = new InteriorAngleSegmentConnector.Minimize();
        connector.connect(boundaries());

        return connector.connectAll().stream()
                .map(Polyline::simplify).collect(Collectors.toList());
    }

    /** {@inheritDoc} */
    @Override
    protected RegionSizeProperties<Vector2D> computeRegionSizeProperties() {
        // handle simple cases
        if (isFull()) {
            return new RegionSizeProperties<>(Double.POSITIVE_INFINITY, null);
        } else if (isEmpty()) {
            return new RegionSizeProperties<>(0, null);
        }

        // compute the size based on the boundary segments
        double quadrilateralAreaSum = 0.0;

        double scaledSumX = 0.0;
        double scaledSumY = 0.0;

        Vector2D startPoint;
        Vector2D endPoint;
        double signedArea;

        for (Segment segment : boundaries()) {

            if (segment.isInfinite()) {
                // at least on boundary is infinite, meaning that
                // the size is also infinite
                quadrilateralAreaSum = Double.POSITIVE_INFINITY;

                break;
            }

            startPoint = segment.getStartPoint();
            endPoint = segment.getEndPoint();

            // compute the area
            signedArea = startPoint.signedArea(endPoint);

            quadrilateralAreaSum += signedArea;

            // compute scaled coordinate values for the barycenter
            scaledSumX += signedArea * (startPoint.getX() + endPoint.getX());
            scaledSumY += signedArea * (startPoint.getY() + endPoint.getY());
        }

        double size = Double.POSITIVE_INFINITY;
        Vector2D barycenter = null;

        // The area is finite only if the computed quadrilateral area is finite and non-negative.
        // Negative areas indicate that the region is inside-out, with a finite outside surrounded
        // by an infinite inside.
        if (quadrilateralAreaSum >= 0.0 && Double.isFinite(quadrilateralAreaSum)) {
            size = 0.5 * quadrilateralAreaSum;

            if (quadrilateralAreaSum > 0.0) {
                barycenter = Vector2D.of(scaledSumX, scaledSumY).multiply(1.0 / (3.0 * quadrilateralAreaSum));
            }
        }

        return new RegionSizeProperties<>(size, barycenter);
    }

    /** Compute the region represented by the given node.
     * @param node the node to compute the region for
     * @return the region represented by the given node
     */
    private ConvexArea computeNodeRegion(final RegionNode2D node) {
        ConvexArea area = ConvexArea.full();

        RegionNode2D child = node;
        RegionNode2D parent;

        while ((parent = child.getParent()) != null) {
            Split<ConvexArea> split = area.split(parent.getCutHyperplane());

            area = child.isMinus() ? split.getMinus() : split.getPlus();

            child = parent;
        }

        return area;
    }

    /** {@inheritDoc} */
    @Override
    protected void invalidate() {
        super.invalidate();

        boundaryPaths = null;
    }

    /** {@inheritDoc} */
    @Override
    protected RegionNode2D createNode() {
        return new RegionNode2D(this);
    }

    /** Return a new {@link RegionBSPTree2D} instance containing the entire space.
     * @return a new {@link RegionBSPTree2D} instance containing the entire space
     */
    public static RegionBSPTree2D full() {
        return new RegionBSPTree2D(true);
    }

    /** Return a new, empty {@link RegionBSPTree2D} instance.
     * @return a new, empty {@link RegionBSPTree2D} instance
     */
    public static RegionBSPTree2D empty() {
        return new RegionBSPTree2D(false);
    }

    /** Construct a tree from a convex area.
     * @param area the area to construct a tree from
     * @return tree instance representing the same area as the given
     *      convex area
     */
    public static RegionBSPTree2D from(final ConvexArea area) {
        final RegionBSPTree2D tree = RegionBSPTree2D.full();
        tree.insert(area.getBoundaries());

        return tree;
    }

    /** Create a new {@link RegionBSPTree2D.Builder} instance for creating BSP
     * trees from boundary representations.
     * @param precision precision context to use for floating point comparisons.
     * @return a new builder instance
     */
    public static Builder builder(final DoublePrecisionContext precision) {
        return new Builder(precision);
    }

    /** BSP tree node for two dimensional Euclidean space.
     */
    public static final class RegionNode2D extends AbstractRegionBSPTree.AbstractRegionNode<Vector2D, RegionNode2D> {
        /** Simple constructor.
         * @param tree the owning tree instance
         */
        private RegionNode2D(AbstractBSPTree<Vector2D, RegionNode2D> tree) {
            super(tree);
        }

        /** Get the region represented by this node. The returned region contains
         * the entire area contained in this node, regardless of the attributes of
         * any child nodes.
         * @return the region represented by this node
         */
        public ConvexArea getNodeRegion() {
            return ((RegionBSPTree2D) getTree()).computeNodeRegion(this);
        }

        /** {@inheritDoc} */
        @Override
        protected RegionNode2D getSelf() {
            return this;
        }
    }

    /** Class used to construct {@link RegionBSPTree2D} instances from boundary representations.
     */
    public static final class Builder {

        /** Precision object used to perform floating point comparisons. This object is
         * used when constructing geometric types.
         */
        private final DoublePrecisionContext precision;

        /** The BSP tree being constructed. */
        private final RegionBSPTree2D tree = RegionBSPTree2D.empty();

        /** Create a new builder instance. The given precision context will be used when
         * constructing geometric types.
         * @param precision precision object used to perform floating point comparisons
         */
        public Builder(final DoublePrecisionContext precision) {
            this.precision = precision;
        }

        /** Add a subline to the tree.
         * @param subline subline to add
         * @return this builder instance
         */
        public Builder add(final SubLine subline) {
            tree.insert(subline);
            return this;
        }

        /** Add a segment to the tree.
         * @param segment segment to add
         * @return this builder instance
         */
        public Builder add(final Segment segment) {
            tree.insert(segment);
            return this;
        }

        /** Add the line segments defined in the given segment path.
         * @param path path containing line segments to add
         * @return this builder instance
         */
        public Builder add(final Polyline path) {
            for (Segment segment : path) {
                add(segment);
            }

            return this;
        }

        /** Add a segment defined by the given points.
         * @param start start point
         * @param end end point
         * @return this builder instance
         */
        public Builder addSegment(final Vector2D start, final Vector2D end) {
            return add(Segment.fromPoints(start, end, precision));
        }

        /** Add segments defining an axis-oriented square with the given corner point and size.
         * @param center center point of the square
         * @param size the size of the square
         * @return this builder instance
         * @throws GeometryValueException if the width or height of the defined rectangle is zero
         *      as evaluated by the precision context.
         */
        public Builder addCenteredSquare(final Vector2D center, final double size) {
            return addCenteredRect(center, size, size);
        }

        /** Add segments defining an axis-oriented square with the given corner point and size.
         * @param corner point in the corner of the square
         * @param size the size of the square
         * @return this builder instance
         * @throws GeometryValueException if the width or height of the defined rectangle is zero
         *      as evaluated by the precision context.
         */
        public Builder addSquare(final Vector2D corner, final double size) {
            return addRect(corner, size, size);
        }

        /** Add segments defining an axis-oriented rectangular region with the given center point and size.
         * @param center center point for the region
         * @param xSize size along the x-axis
         * @param ySize size along the y-axis
         * @return this builder instance
         * @throws GeometryValueException if the width or height of the defined rectangle is zero
         *      as evaluated by the precision context.
         */
        public Builder addCenteredRect(final Vector2D center, final double xSize, final double ySize) {
            return addRect(Vector2D.of(
                        center.getX() - (0.5 * xSize),
                        center.getY() - (0.5 * ySize)
                    ), xSize, ySize);
        }

        /** Add segments defining an axis-oriented rectangular region. The region
         * is constructed by taking {@code pt} as one corner of the region and adding {@code xDelta}
         * and {@code yDelta} to its components to create the opposite corner. If {@code xDelta}
         * and {@code yDelta} are both positive, then the constructed rectangle will have {@code pt}
         * as its lower-left corner and will have a width and height of {@code xDelta} and {@code yDelta}
         * respectively.
         * @param pt point lying in a corner of the region
         * @param xDelta distance to move along the x axis to place the other points in the
         *      rectangle; this value may be negative, in which case {@code pt} will lie
         *      on the right side of the constructed rectangle
         * @param yDelta distance to move along the y axis to place the other points in the
         *      rectangle; this value may be negative, in which case {@code pt} will lie
         *      on the top of the rectangle
         * @return this builder instance
         * @throws GeometryValueException if the width or height of the defined rectangle is zero
         *      as evaluated by the precision context.
         */
        public Builder addRect(final Vector2D pt, final double xDelta, final double yDelta) {
            return addRect(pt, Vector2D.of(
                    pt.getX() + xDelta,
                    pt.getY() + yDelta));
        }

        /** Add segments defining an axis-oriented rectangular region. The points {@code a} and {@code b}
         * are taken to represent opposite corner points in the rectangle and may be specified in any order.
         * @param a first corner point in the rectangle (opposite of {@code b})
         * @param b second corner point in the rectangle (opposite of {@code a})
         * @return this builder instance
         * @throws GeometryValueException if the width or height of the defined rectangle is zero
         *      as evaluated by the precision context.
         */
        public Builder addRect(final Vector2D a, final Vector2D b) {
            final double minX = Math.min(a.getX(), b.getX());
            final double maxX = Math.max(a.getX(), b.getX());

            final double minY = Math.min(a.getY(), b.getY());
            final double maxY = Math.max(a.getY(), b.getY());

            if (precision.eq(minX, maxX) || precision.eq(minY, maxY)) {
                throw new GeometryValueException("Rectangle has zero size: " + a + ", " + b + ".");
            }

            final Vector2D lowerLeft = Vector2D.of(minX, minY);
            final Vector2D upperLeft = Vector2D.of(minX, maxY);

            final Vector2D upperRight = Vector2D.of(maxX, maxY);
            final Vector2D lowerRight = Vector2D.of(maxX, minY);

            addSegment(lowerLeft, lowerRight);
            addSegment(upperRight, upperLeft);
            addSegment(lowerRight, upperRight);
            addSegment(upperLeft, lowerLeft);

            return this;
        }

        /** Get the created BSP tree.
         * @return the created BSP tree
         */
        public RegionBSPTree2D build() {
            return tree;
        }
    }

    /** Class used to project points onto the 2D region boundary.
     */
    private static final class BoundaryProjector2D extends BoundaryProjector<Vector2D, RegionNode2D> {
        /** Simple constructor.
         * @param point the point to project onto the region's boundary
         */
        BoundaryProjector2D(final Vector2D point) {
            super(point);
        }

        /** {@inheritDoc} */
        @Override
        protected Vector2D disambiguateClosestPoint(final Vector2D target, final Vector2D a, final Vector2D b) {
            // return the point with the smallest coordinate values
            final int cmp = Vector2D.COORDINATE_ASCENDING_ORDER.compare(a, b);
            return cmp < 0 ? a : b;
        }
    }
}
