/*
 * 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.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.commons.geometry.core.Transform;
import org.apache.commons.geometry.core.partitioning.AbstractConvexHyperplaneBoundedRegion;
import org.apache.commons.geometry.core.partitioning.ConvexSubHyperplane;
import org.apache.commons.geometry.core.partitioning.Hyperplane;
import org.apache.commons.geometry.core.partitioning.Split;
import org.apache.commons.geometry.euclidean.twod.ConvexArea;

/** Class representing a finite or infinite convex volume in Euclidean 3D space.
 * The boundaries of this area, if any, are composed of convex subplanes.
 */
public final class ConvexVolume extends AbstractConvexHyperplaneBoundedRegion<Vector3D, ConvexSubPlane> {
    /** Instance representing the full 3D volume. */
    private static final ConvexVolume FULL = new ConvexVolume(Collections.emptyList());

    /** Simple constructor. Callers are responsible for ensuring that the given path
     * represents the boundary of a convex area. No validation is performed.
     * @param boundaries the boundaries of the convex area
     */
    private ConvexVolume(final List<ConvexSubPlane> boundaries) {
        super(boundaries);
    }

    /** {@inheritDoc} */
    @Override
    public double getSize() {
        if (isFull()) {
            return Double.POSITIVE_INFINITY;
        }

        double volumeSum = 0.0;

        for (ConvexSubPlane subplane : getBoundaries()) {
            if (subplane.isInfinite()) {
                return Double.POSITIVE_INFINITY;
            }

            final Plane plane = subplane.getPlane();
            final ConvexArea subarea = subplane.getSubspaceRegion();

            final Vector3D facetBarycenter = subplane.getHyperplane().toSpace(
                    subarea.getBarycenter());


            volumeSum += subarea.getSize() * facetBarycenter.dot(plane.getNormal());
        }

        return volumeSum / 3.0;
    }

    /** {@inheritDoc} */
    @Override
    public Vector3D getBarycenter() {
        double volumeSum = 0.0;

        double sumX = 0.0;
        double sumY = 0.0;
        double sumZ = 0.0;

        for (ConvexSubPlane subplane : getBoundaries()) {
            if (subplane.isInfinite()) {
                return null;
            }

            final Plane plane = subplane.getPlane();
            final ConvexArea subarea = subplane.getSubspaceRegion();

            final Vector3D facetBarycenter = subplane.getHyperplane().toSpace(
                    subarea.getBarycenter());

            double scaledVolume = subarea.getSize() * facetBarycenter.dot(plane.getNormal());

            volumeSum += scaledVolume;

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

        if (volumeSum > 0) {
            double 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);
            return Vector3D.of(
                    sumX * barycenterScale,
                    sumY * barycenterScale,
                    sumZ * barycenterScale);
        }

        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Split<ConvexVolume> split(final Hyperplane<Vector3D> splitter) {
        return splitInternal(splitter, this, ConvexSubPlane.class, ConvexVolume::new);
    }

    /** {@inheritDoc} */
    @Override
    public ConvexSubPlane trim(final ConvexSubHyperplane<Vector3D> convexSubHyperplane) {
        return (ConvexSubPlane) super.trim(convexSubHyperplane);
    }

    /** Return a new instance transformed by the argument.
     * @param transform transform to apply
     * @return a new instance transformed by the argument
     */
    public ConvexVolume transform(final Transform<Vector3D> transform) {
        return transformInternal(transform, this, ConvexSubPlane.class, ConvexVolume::new);
    }

    /** Return a BSP tree instance representing the same region as the current instance.
     * @return a BSP tree instance representing the same region as the current instance
     */
    public RegionBSPTree3D toTree() {
        return RegionBSPTree3D.from(this);
    }

    /** Return an instance representing the full 3D volume.
     * @return an instance representing the full 3D volume.
     */
    public static ConvexVolume full() {
        return FULL;
    }

    /** Create a convex volume formed by the intersection of the negative half-spaces of the
     * given bounding planes. The returned instance represents the volume that is on the
     * minus side of all of the given plane. Note that this method does not support volumes
     * of zero size (ie, infinitely thin volumes or points.)
     * @param planes planes used to define the convex area
     * @return a new convex volume instance representing the volume on the minus side of all
     *      of the bounding plane or an instance representing the full space if the collection
     *      is empty
     * @throws org.apache.commons.geometry.core.exception.GeometryException if the given set of bounding
     *      planes do not form a convex volume, meaning that there is no region that is on the minus side
     *      of all of the bounding planes.
     */
    public static ConvexVolume fromBounds(final Plane... planes) {
        return fromBounds(Arrays.asList(planes));
    }

    /** Create a convex volume formed by the intersection of the negative half-spaces of the
     * given bounding planes. The returned instance represents the volume that is on the
     * minus side of all of the given plane. Note that this method does not support volumes
     * of zero size (ie, infinitely thin volumes or points.)
     * @param boundingPlanes planes used to define the convex area
     * @return a new convex volume instance representing the volume on the minus side of all
     *      of the bounding plane or an instance representing the full space if the collection
     *      is empty
     * @throws org.apache.commons.geometry.core.exception.GeometryException if the given set of bounding planes
     *      do not form a convex volume, meaning that there is no region that is on the minus side of all of
 *          the bounding planes.
     */
    public static ConvexVolume fromBounds(final Iterable<Plane> boundingPlanes) {
        final List<ConvexSubPlane> subplanes = new ConvexRegionBoundaryBuilder<>(ConvexSubPlane.class)
                .build(boundingPlanes);
        return subplanes.isEmpty() ? full() : new ConvexVolume(subplanes);
    }
}
