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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

import org.apache.commons.geometry.core.Point;
import org.apache.commons.geometry.core.RegionLocation;
import org.apache.commons.geometry.core.Transform;
import org.apache.commons.geometry.core.exception.GeometryException;

/** Base class for convex hyperplane-bounded regions. This class provides generic implementations of many
 * algorithms related to convex regions.
 * @param <P> Point implementation type
 * @param <S> Convex subhyperplane implementation type
 */
public abstract class AbstractConvexHyperplaneBoundedRegion<P extends Point<P>, S extends ConvexSubHyperplane<P>>
    implements HyperplaneBoundedRegion<P> {
    /** List of boundaries for the region. */
    private final List<S> boundaries;

    /** Simple constructor. Callers are responsible for ensuring that the given list of subhyperplanes
     * represent a valid convex region boundary. No validation is performed.
     * @param boundaries the boundaries of the convex region
     */
    protected AbstractConvexHyperplaneBoundedRegion(final List<S> boundaries) {
        this.boundaries = Collections.unmodifiableList(boundaries);
    }

    /** Get the boundaries of the convex region. The exact ordering of the boundaries
     * is not guaranteed.
     * @return the boundaries of the convex region
     */
    public List<S> getBoundaries() {
        return boundaries;
    }

    /** {@inheritDoc} */
    @Override
    public boolean isFull() {
        // no boundaries => no outside
        return boundaries.isEmpty();
    }

    /** {@inheritDoc}
     *
     * <p>This method always returns false.</p>
     */
    @Override
    public boolean isEmpty() {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public double getBoundarySize() {
        double sum = 0.0;
        for (final S boundary : boundaries) {
            sum += boundary.getSize();
        }

        return sum;
    }

    /** {@inheritDoc} */
    @Override
    public RegionLocation classify(P pt) {
        boolean isOn = false;

        HyperplaneLocation loc;
        for (final S boundary : boundaries) {
            loc = boundary.getHyperplane().classify(pt);

            if (loc == HyperplaneLocation.PLUS) {
                return RegionLocation.OUTSIDE;
            } else if (loc == HyperplaneLocation.ON) {
                isOn = true;
            }
        }

        return isOn ? RegionLocation.BOUNDARY : RegionLocation.INSIDE;
    }

    /** {@inheritDoc} */
    @Override
    public P project(P pt) {

        P projected;
        double dist;

        P closestPt = null;
        double closestDist = Double.POSITIVE_INFINITY;

        for (final S boundary : boundaries) {
            projected = boundary.closest(pt);
            dist = pt.distance(projected);

            if (projected != null && (closestPt == null || dist < closestDist)) {
                closestPt = projected;
                closestDist = dist;
            }
        }

        return closestPt;
    }

    /** Trim the given convex subhyperplane to the portion contained inside this instance.
     * @param convexSubHyperplane convex subhyperplane to trim. Null is returned if the subhyperplane
     * does not intersect the instance.
     * @return portion of the argument that lies entirely inside the region represented by
     *      this instance, or null if it does not intersect.
     */
    public ConvexSubHyperplane<P> trim(final ConvexSubHyperplane<P> convexSubHyperplane) {
        ConvexSubHyperplane<P> remaining = convexSubHyperplane;
        for (final S boundary : boundaries) {
            remaining = remaining.split(boundary.getHyperplane()).getMinus();
            if (remaining == null) {
                break;
            }
        }

        return remaining;
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append(this.getClass().getSimpleName())
            .append("[boundaries= ")
            .append(boundaries);

        return sb.toString();
    }

    /** Generic, internal transform method. Subclasses should use this to implement their own transform methods.
     * @param transform the transform to apply to the instance
     * @param thisInstance a reference to the current instance; this is passed as
     *      an argument in order to allow it to be a generic type
     * @param subhpType the type used for the boundary subhyperplanes
     * @param factory function used to create new convex region instances
     * @param <R> Region implementation type
     * @return the result of the transform operation
     */
    protected <R extends AbstractConvexHyperplaneBoundedRegion<P, S>> R transformInternal(
            final Transform<P> transform, final R thisInstance, final Class<S> subhpType,
            final Function<List<S>, R> factory) {

        if (isFull()) {
            return thisInstance;
        }

        final List<S> origBoundaries = getBoundaries();

        final int size = origBoundaries.size();
        final List<S> tBoundaries = new ArrayList<>(size);

        // determine if the hyperplanes should be reversed
        final S boundary = origBoundaries.get(0);
        ConvexSubHyperplane<P> tBoundary = boundary.transform(transform);

        final boolean reverseDirection = swapsInsideOutside(transform);

        // transform all of the segments
        if (reverseDirection) {
            tBoundary = tBoundary.reverse();
        }
        tBoundaries.add(subhpType.cast(tBoundary));

        for (int i = 1; i < origBoundaries.size(); ++i) {
            tBoundary = origBoundaries.get(i).transform(transform);

            if (reverseDirection) {
                tBoundary = tBoundary.reverse();
            }

            tBoundaries.add(subhpType.cast(tBoundary));
        }

        return factory.apply(tBoundaries);
    }

    /** Return true if the given transform swaps the inside and outside of
     * the region.
     *
     * <p>The default behavior of this method is to return true if the transform
     * does not preserve spatial orientation (ie, {@link Transform#preservesOrientation()}
     * is false). Subclasses may need to override this method to implement the correct
     * behavior for their space and dimension.</p>
     * @param transform transform to check
     * @return true if the given transform swaps the interior and exterior of
     *      the region
     */
    protected boolean swapsInsideOutside(final Transform<P> transform) {
        return !transform.preservesOrientation();
    }

    /** Generic, internal split method. Subclasses should call this from their {@link #split(Hyperplane)} methods.
     * @param splitter splitting hyperplane
     * @param thisInstance a reference to the current instance; this is passed as
     *      an argument in order to allow it to be a generic type
     * @param subhpType the type used for the boundary subhyperplanes
     * @param factory function used to create new convex region instances
     * @param <R> Region implementation type
     * @return the result of the split operation
     */
    protected <R extends AbstractConvexHyperplaneBoundedRegion<P, S>> Split<R> splitInternal(
            final Hyperplane<P> splitter, final R thisInstance, final Class<S> subhpType,
            final Function<List<S>, R> factory) {

        if (isFull()) {
            final R minus = factory.apply(Arrays.asList(subhpType.cast(splitter.span())));
            final R plus = factory.apply(Arrays.asList(subhpType.cast(splitter.reverse().span())));

            return new Split<>(minus, plus);
        } else {
            final ConvexSubHyperplane<P> trimmedSplitter = trim(splitter.span());

            if (trimmedSplitter == null) {
                // The splitter lies entirely outside of the region; we need
                // to determine whether we lie on the plus or minus side of the splitter.
                // We can use the first boundary to determine this. If the boundary is entirely
                // on the minus side of the splitter or lies directly on the splitter and has
                // the same orientation, then the area lies on the minus side of the splitter.
                // Otherwise, it lies on the plus side.
                final ConvexSubHyperplane<P> testSegment = boundaries.get(0);
                final SplitLocation testLocation = testSegment.split(splitter).getLocation();

                if (SplitLocation.MINUS == testLocation ||
                        (SplitLocation.NEITHER == testLocation &&
                            splitter.similarOrientation(testSegment.getHyperplane()))) {
                    return new Split<>(thisInstance, null);
                }

                return new Split<>(null, thisInstance);
            }

            final List<S> minusBoundaries = new ArrayList<>();
            final List<S> plusBoundaries = new ArrayList<>();

            Split<? extends ConvexSubHyperplane<P>> split;
            ConvexSubHyperplane<P> minusBoundary;
            ConvexSubHyperplane<P> plusBoundary;

            for (final S boundary : boundaries) {
                split = boundary.split(splitter);

                minusBoundary = split.getMinus();
                plusBoundary = split.getPlus();

                if (minusBoundary != null) {
                    minusBoundaries.add(subhpType.cast(minusBoundary));
                }

                if (plusBoundary != null) {
                    plusBoundaries.add(subhpType.cast(plusBoundary));
                }
            }

            minusBoundaries.add(subhpType.cast(trimmedSplitter));
            plusBoundaries.add(subhpType.cast(trimmedSplitter.reverse()));

            return new Split<>(factory.apply(minusBoundaries), factory.apply(plusBoundaries));
        }
    }

    /** Internal class encapsulating the logic for building convex region boundaries from collections of
     * hyperplanes.
     * @param <P> Point implementation type
     * @param <S> ConvexSubHyperplane implementation type
     */
    protected static class ConvexRegionBoundaryBuilder<P extends Point<P>, S extends ConvexSubHyperplane<P>> {

        /** Convex subhyperplane implementation type. */
        private final Class<S> subhyperplaneType;

        /** Construct a new instance for building convex region boundaries with the given convex subhyperplane
         * implementation type.
         * @param subhyperplaneType Convex subhyperplane implementation type
         */
        public ConvexRegionBoundaryBuilder(final Class<S> subhyperplaneType) {
            this.subhyperplaneType = subhyperplaneType;
        }

        /** Compute a list of convex subhyperplanes representing the boundaries of the convex region
         * bounded by the given collection of hyperplanes.
         * @param bounds hyperplanes defining the convex region
         * @return a list of convex subhyperplanes representing the boundaries of the convex region
         * @throws GeometryException if the given hyperplanes do not form a convex region
         */
        public List<S> build(final Iterable<? extends Hyperplane<P>> bounds) {

            final List<S> boundaries = new ArrayList<>();

            // cut each hyperplane by every other hyperplane in order to get the subplane boundaries
            boolean notConvex = false;
            int outerIdx = 0;
            ConvexSubHyperplane<P> subhp;

            for (final Hyperplane<P> hp : bounds) {
                ++outerIdx;
                subhp = hp.span();

                int innerIdx = 0;
                for (final Hyperplane<P> splitter : bounds) {
                    ++innerIdx;

                    if (hp != splitter) {
                        final Split<? extends ConvexSubHyperplane<P>> split = subhp.split(splitter);

                        if (split.getLocation() == SplitLocation.NEITHER) {
                            if (hp.similarOrientation(splitter)) {
                                // two or more splitters are the equivalent; only
                                // use the segment from the first one
                                if (outerIdx > innerIdx) {
                                    subhp = null;
                                }
                            } else {
                                // two or more splitters are coincident and have opposite
                                // orientations, meaning that no area is on the minus side
                                // of both
                                notConvex = true;
                                break;
                            }
                        } else {
                            subhp = subhp.split(splitter).getMinus();
                        }

                        if (subhp == null) {
                            break;
                        }
                    } else if (outerIdx > innerIdx) {
                        // this hyperplane is duplicated in the list; skip all but the
                        // first insertion of its subhyperplane
                        subhp = null;
                        break;
                    }
                }

                if (notConvex) {
                    break;
                }

                if (subhp != null) {
                    boundaries.add(subhyperplaneType.cast(subhp));
                }
            }

            if (notConvex || (outerIdx > 0 && boundaries.isEmpty())) {
                throw new GeometryException("Bounding hyperplanes do not produce a convex region: " + bounds);
            }

            return boundaries;
        }
    }
}
