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

import java.util.ArrayList;
import java.util.Arrays;
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.SubHyperplane;
import org.apache.commons.geometry.core.partitioning.bsp.AbstractBSPTree;
import org.apache.commons.geometry.core.partitioning.bsp.AbstractRegionBSPTree;
import org.apache.commons.geometry.core.partitioning.bsp.BSPTreeVisitor;
import org.apache.commons.geometry.core.partitioning.bsp.RegionCutBoundary;
import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
import org.apache.commons.geometry.euclidean.twod.Polyline;
import org.apache.commons.geometry.euclidean.twod.RegionBSPTree2D;
import org.apache.commons.geometry.euclidean.twod.Vector2D;

/** Binary space partitioning (BSP) tree representing a region in three dimensional
 * Euclidean space.
 */
public final class RegionBSPTree3D extends AbstractRegionBSPTree<Vector3D, RegionBSPTree3D.RegionNode3D> {
    /** Create a new, empty region. */
    public RegionBSPTree3D() {
        this(false);
    }

    /** Create a new region. If {@code full} is true, then the region will
     * represent the entire 3D space. Otherwise, it will be empty.
     * @param full whether or not the region should contain the entire
     *      3D space or be empty
     */
    public RegionBSPTree3D(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 RegionBSPTree3D copy() {
        RegionBSPTree3D result = RegionBSPTree3D.empty();
        result.copy(this);

        return result;
    }

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

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

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

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

        return result;
    }

    /** Recursive method to compute the convex volumes of all inside leaf nodes in the subtree rooted at the given
     * node. The computed convex volumes are added to the given list.
     * @param node root of the subtree to compute the convex volumes for
     * @param nodeVolume the convex volume for the current node; this will be split by the node's cut hyperplane to
     *      form the convex volumes for any child nodes
     * @param result list containing the results of the computation
     */
    private void toConvexRecursive(final RegionNode3D node, final ConvexVolume nodeVolume,
            final List<ConvexVolume> result) {

        if (node.isLeaf()) {
            // base case; only add to the result list if the node is inside
            if (node.isInside()) {
                result.add(nodeVolume);
            }
        } else {
            // recurse
            Split<ConvexVolume> split = nodeVolume.split(node.getCutHyperplane());

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

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

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

        return projector.getProjected();
    }

    /** Find the first intersection of the given ray/line segment with the boundary of
     * the region. The return value is the cut subhyperplane of the node containing the
     * intersection. Null is returned if no intersection exists.
     * @param ray ray to intersect with the region
     * @return the node cut subhyperplane containing the intersection or null if no
     *      intersection exists
     */
    public ConvexSubPlane raycastFirst(final Segment3D ray) {
        final RaycastIntersectionVisitor visitor = new RaycastIntersectionVisitor(ray);
        getRoot().accept(visitor);

        return visitor.getIntersectionCut();
    }

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

        RegionSizePropertiesVisitor visitor = new RegionSizePropertiesVisitor();
        accept(visitor);

        return visitor.getRegionSizeProperties();
    }

    /** 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 ConvexVolume computeNodeRegion(final RegionNode3D node) {
        ConvexVolume volume = ConvexVolume.full();

        RegionNode3D child = node;
        RegionNode3D parent;

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

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

            child = parent;
        }

        return volume;
    }

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

    /** Return a new instance containing all of 3D space.
     * @return a new instance containing all of 3D space.
     */
    public static RegionBSPTree3D full() {
        return new RegionBSPTree3D(true);
    }

    /** Return a new, empty instance. The represented region is completely empty.
     * @return a new, empty instance.
     */
    public static RegionBSPTree3D empty() {
        return new RegionBSPTree3D(false);
    }

    /** Create a new BSP tree instance representing the same region as the argument.
     * @param volume convex volume instance
     * @return a new BSP tree instance representing the same region as the argument
     */
    public static RegionBSPTree3D from(final ConvexVolume volume) {
        RegionBSPTree3D tree = RegionBSPTree3D.full();
        tree.insert(volume.getBoundaries());

        return tree;
    }

    /** Create a new {@link RegionBSPTree3D.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 three dimensional Euclidean space.
     */
    public static final class RegionNode3D extends AbstractRegionBSPTree.AbstractRegionNode<Vector3D, RegionNode3D> {
        /** Simple constructor.
         * @param tree the owning tree instance
         */
        protected RegionNode3D(AbstractBSPTree<Vector3D, RegionNode3D> 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 ConvexVolume getNodeRegion() {
            return ((RegionBSPTree3D) getTree()).computeNodeRegion(this);
        }

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

    /** Class used to construct {@link RegionBSPTree3D} 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 RegionBSPTree3D tree = RegionBSPTree3D.empty();

        /** List of vertices to use for indexed facet operations. */
        private List<Vector3D> vertexList;

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

        /** Set the list of vertices to use for indexed facet operations.
         * @param vertices array of vertices
         * @return this builder instance
         * @see #addIndexedFacet(int...)
         * @see #addIndexedFacet(List)
         * @see #addIndexedFacets(int[][])
         */
        public Builder withVertexList(final Vector3D... vertices) {
            return withVertexList(Arrays.asList(vertices));
        }

        /** Set the list of vertices to use for indexed facet operations.
         * @param vertices list of vertices
         * @return this builder instance
         * @see #addIndexedFacet(int...)
         * @see #addIndexedFacet(List)
         * @see #addIndexedFacets(int[][])
         */
        public Builder withVertexList(final List<Vector3D> vertices) {
            this.vertexList = vertices;
            return this;
        }

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

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

        /** Add a facet defined by the given array of vertices. The vertices
         * are considered to form a loop, even if the first vertex is not included
         * again at the end of the array.
         * @param vertices array of vertices defining the facet
         * @return this builder instance
         */
        public Builder addFacet(final Vector3D... vertices) {
            return addFacet(Arrays.asList(vertices));
        }

        /** Add a facet defined by the given list of vertices. The vertices
         * are considered to form a loop, even if the first vertex is not included
         * again at the end of the list.
         * @param vertices list of vertices defining the facet
         * @return this builder instance
         */
        public Builder addFacet(final List<Vector3D> vertices) {
            // if there are only 3 vertices, then we know for certain that the area is convex
            if (vertices.size() < 4) {
                return add(ConvexSubPlane.fromVertexLoop(vertices, precision));
            }

            final Plane plane = Plane.fromPoints(vertices, precision);
            final List<Vector2D> subspaceVertices = plane.toSubspace(vertices);

            final Polyline path = Polyline.fromVertexLoop(subspaceVertices, precision);
            return add(new SubPlane(plane, path.toTree()));
        }

        /** Add multiple facets, each one defined by an array of indices into the current
         * vertex list.
         * @param facets array of facet definitions, where each definition consists of an
         *      array of indices into the current vertex list
         * @return this builder instance
         * @see #withVertexList(List)
         */
        public Builder addIndexedFacets(int[][] facets) {
            for (int[] facet : facets) {
                addIndexedFacet(facet);
            }

            return this;
        }

        /** Add a facet defined by an array of indices into the current vertex list.
         * @param vertexIndices indices into the current vertex list, defining the vertices
         *      for the facet
         * @return this builder instance
         * @see #withVertexList(List)
         */
        public Builder addIndexedFacet(int... vertexIndices) {
            final Vector3D[] vertices = new Vector3D[vertexIndices.length];
            for (int i = 0; i < vertexIndices.length; ++i) {
                vertices[i] = vertexList.get(vertexIndices[i]);
            }

            return addFacet(vertices);
        }

        /** Add a facet defined by a list of indices into the current vertex list.
         * @param vertexIndices indices into the current vertex list, defining the vertices
         *      for the facet
         * @return this builder instance
         * @see #withVertexList(List)
         */
        public Builder addIndexedFacet(final List<Integer> vertexIndices) {
            final List<Vector3D> vertices = vertexIndices.stream()
                    .map(idx -> vertexList.get(idx)).collect(Collectors.toList());

            return addFacet(vertices);
        }

        /** Add an axis-oriented cube with the given dimensions to this instance.
        * @param center the cube center point
        * @param size the size of the cube
        * @return this builder instance
        * @throws GeometryValueException if the width, height, or depth of the defined region is zero
        *      as evaluated by the precision context.
        */
        public Builder addCenteredCube(final Vector3D center, final double size) {
            return addCenteredRect(center, size, size, size);
        }

        /** Add an axis-oriented cube with the given dimensions to this instance.
         * @param corner a corner of the cube
         * @param size the size of the cube
         * @return this builder instance
         * @throws GeometryValueException if the width, height, or depth of the defined region is zero
         *      as evaluated by the precision context.
         */
        public Builder addCube(final Vector3D corner, final double size) {
            return addRect(corner, size, size, size);
        }

        /** Add an axis-oriented rectangular prism to this instance. The prism is centered at the given point and
         * has the specified dimensions.
         * @param center center point for the rectangular prism
         * @param xSize size of the prism along the x-axis
         * @param ySize size of the prism along the y-axis
         * @param zSize size of the prism along the z-axis
         * @return this builder instance
         * @throws GeometryValueException if the width, height, or depth of the defined region is zero
         *      as evaluated by the precision context.
         */
        public Builder addCenteredRect(final Vector3D center, final double xSize, final double ySize,
                final double zSize) {

            return addRect(Vector3D.of(
                        center.getX() - (xSize * 0.5),
                        center.getY() - (ySize * 0.5),
                        center.getZ() - (zSize * 0.5)
                    ), xSize, ySize, zSize);
        }

        /** Add an axis-oriented rectangular prism to this instance. The prism
         * is constructed by taking {@code pt} as one corner of the region and adding {@code xDelta},
         * {@code yDelta}, and {@code zDelta} to its components to create the opposite corner.
         * @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
         *      prism; this value may be negative.
         * @param yDelta distance to move along the y axis to place the other points in the
         *      prism; this value may be negative.
         * @param zDelta distance to move along the z axis to place the other points in the
         *      prism; this value may be negative.
         * @return this builder instance
         * @throws GeometryValueException if the width, height, or depth of the defined region is zero
         *      as evaluated by the precision context.
         */
        public Builder addRect(final Vector3D pt, final double xDelta, final double yDelta, final double zDelta) {
            return addRect(pt, Vector3D.of(
                    pt.getX() + xDelta,
                    pt.getY() + yDelta,
                    pt.getZ() + zDelta));
        }

        /** Add an axis-oriented rectangular prism to this instance. The points {@code a} and {@code b}
         * are taken to represent opposite corner points in the prism and may be specified in any order.
         * @param a first corner point in the rectangular prism (opposite of {@code b})
         * @param b second corner point in the rectangular prism (opposite of {@code a})
         * @return this builder instance
         * @throws GeometryValueException if the width, height, or depth of the defined region is zero
         *      as evaluated by the precision context.
         */
        public Builder addRect(final Vector3D a, final Vector3D 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());

            final double minZ = Math.min(a.getZ(), b.getZ());
            final double maxZ = Math.max(a.getZ(), b.getZ());

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

            final Vector3D[] vertices = {
                Vector3D.of(minX, minY, minZ),
                Vector3D.of(maxX, minY, minZ),
                Vector3D.of(maxX, maxY, minZ),
                Vector3D.of(minX, maxY, minZ),

                Vector3D.of(minX, minY, maxZ),
                Vector3D.of(maxX, minY, maxZ),
                Vector3D.of(maxX, maxY, maxZ),
                Vector3D.of(minX, maxY, maxZ)
            };

            addFacet(vertices[0], vertices[3], vertices[2], vertices[1]);
            addFacet(vertices[4], vertices[5], vertices[6], vertices[7]);

            addFacet(vertices[5], vertices[1], vertices[2], vertices[6]);
            addFacet(vertices[0], vertices[4], vertices[7], vertices[3]);

            addFacet(vertices[0], vertices[1], vertices[5], vertices[4]);
            addFacet(vertices[3], vertices[7], vertices[6], vertices[2]);

            return this;
        }

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

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

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

    /** Visitor for computing geometric properties for 3D BSP tree instances.
     *  The volume of the region is computed using the equation
     *  <code>V = (1/3)*&Sigma;<sub>F</sub>[(C<sub>F</sub>&sdot;N<sub>F</sub>)*area(F)]</code>,
     *  where <code>F</code> represents each face in the region, <code>C<sub>F</sub></code>
     *  represents the barycenter of the face, and <code>N<sub>F</sub></code> represents the
     *  normal of the face. (More details can be found in the article
     *  <a href="https://en.wikipedia.org/wiki/Polyhedron#Volume">here</a>.)
     *  This essentially splits up the region into pyramids with a 2D face forming
     *  the base of each pyramid. The barycenter is computed in a similar way. The barycenter
     *  of each pyramid is calculated using the fact that it is located 3/4 of the way along the
     *  line from the apex to the base. The region barycenter then becomes the volume-weighted
     *  average of these pyramid centers.
     *  @see https://en.wikipedia.org/wiki/Polyhedron#Volume
     */
    private static final class RegionSizePropertiesVisitor implements BSPTreeVisitor<Vector3D, RegionNode3D> {

        /** Accumulator for facet volume contributions. */
        private double volumeSum;

        /** Barycenter contribution x coordinate accumulator. */
        private double sumX;

        /** Barycenter contribution y coordinate accumulator. */
        private double sumY;

        /** Barycenter contribution z coordinate accumulator. */
        private double sumZ;

        /** {@inheritDoc} */
        @Override
        public Result visit(final RegionNode3D node) {
            if (node.isInternal()) {
                RegionCutBoundary<Vector3D> boundary = node.getCutBoundary();
                addFacetContribution(boundary.getOutsideFacing(), false);
                addFacetContribution(boundary.getInsideFacing(), true);
            }

            return Result.CONTINUE;
        }

        /** Return the computed size properties for the visited region.
         * @return the computed size properties for the visited region.
         */
        public RegionSizeProperties<Vector3D> getRegionSizeProperties() {
            double size = Double.POSITIVE_INFINITY;
            Vector3D barycenter = null;

            // we only have a finite size if the volume sum is finite and positive
            // (negative indicates a finite outside surrounded by an infinite inside)
            if (Double.isFinite(volumeSum) && volumeSum > 0.0) {
                // apply the 1/3 pyramid volume scaling factor
                size = volumeSum / 3.0;

                // Since the volume we used when adding together the facet contributions
                // was 3x the actual pyramid size, we'll multiply by 1/4 here instead
                // of 3/4 to adjust for the actual barycenter position in each pyramid.
                final double barycenterScale = 1.0 / (4 * size);
                barycenter =  Vector3D.of(
                        sumX * barycenterScale,
                        sumY * barycenterScale,
                        sumZ * barycenterScale);
            }

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

        /** Add the facet contribution of the given node cut boundary. If {@code reverse} is true,
         * the volume of the facet contribution is reversed before being added to the total.
         * @param boundary node cut boundary
         * @param reverse if true, the facet contribution is reversed before being added to the total.
         */
        private void addFacetContribution(final SubHyperplane<Vector3D> boundary, boolean reverse) {
            SubPlane subplane = (SubPlane) boundary;
            RegionBSPTree2D base = subplane.getSubspaceRegion();

            double area = base.getSize();
            Vector2D baseBarycenter = base.getBarycenter();

            if (Double.isInfinite(area)) {
                volumeSum = Double.POSITIVE_INFINITY;
            } else if (baseBarycenter != null) {
                Plane plane = subplane.getPlane();
                Vector3D facetBarycenter = plane.toSpace(base.getBarycenter());

                // the volume here is actually 3x the actual pyramid volume; we'll apply
                // the final scaling all at once at the end
                double scaledVolume = area * facetBarycenter.dot(plane.getNormal());
                if (reverse) {
                    scaledVolume = -scaledVolume;
                }

                volumeSum += scaledVolume;

                sumX += scaledVolume * facetBarycenter.getX();
                sumY += scaledVolume * facetBarycenter.getY();
                sumZ += scaledVolume * facetBarycenter.getZ();
            }
        }
    }

    /** BSP tree visitor that locates the node cut subhyperplane for the first intersection between a
     * given line segment and BSP tree region boundary.
     */
    private static final class RaycastIntersectionVisitor implements BSPTreeVisitor<Vector3D, RegionNode3D> {

        /** The line segment to intersect with the BSP tree. */
        private final Segment3D segment;

        /** The node cut subhyperplane containing the first boundary intersection. */
        private ConvexSubPlane intersectionCut;

        /** Create a new instance that locates the first boundary intersection between the given line segment and
         * the visited BSP tree.
         * @param segment segment to intersect with the BSP tree region boundary
         */
        RaycastIntersectionVisitor(final Segment3D segment) {
            this.segment = segment;
        }

        /** Get the node cut subhyperplane containing the first intersection between the configured line segment
         * and the BSP tree region boundary. This must be called after the tree nodes have been visited.
         * @return the node cut subhyperplane containing the first intersection between the configured line segment
         *      and the BSP tree region boundary or null if no such intersection was found
         */
        public ConvexSubPlane getIntersectionCut() {
            return intersectionCut;
        }

        /** {@inheritDoc} */
        @Override
        public Order visitOrder(final RegionNode3D internalNode) {
            final Plane cut = (Plane) internalNode.getCutHyperplane();
            final Line3D line = segment.getLine();

            final boolean plusIsNear = line.getDirection().dot(cut.getNormal()) < 0;

            return plusIsNear ?
                    Order.PLUS_NODE_MINUS :
                    Order.MINUS_NODE_PLUS;
        }

        /** {@inheritDoc} */
        @Override
        public Result visit(final RegionNode3D node) {
            if (node.isInternal()) {
                // check if the line segment intersects the cut subhyperplane
                final Line3D line = segment.getLine();
                final Vector3D intersection = ((Plane) node.getCutHyperplane()).intersection(line);

                if (intersection != null && segment.contains(intersection)) {

                    final RegionCutBoundary<Vector3D> boundary = node.getCutBoundary();

                    // check if the intersection point lies on the region boundary
                    if ((boundary.getInsideFacing() != null && boundary.getInsideFacing().contains(intersection)) ||
                            boundary.getOutsideFacing() != null && boundary.getOutsideFacing().contains(intersection)) {

                        intersectionCut = (ConvexSubPlane) node.getCut();

                        return Result.TERMINATE;
                    }
                }
            }

            return Result.CONTINUE;
        }
    }
}
