/*
 * 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.io.File;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.geometry.core.partitioning.BSPTree;
import org.apache.commons.geometry.core.partitioning.BSPTreeVisitor;
import org.apache.commons.geometry.core.partitioning.BoundaryAttribute;
import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
import org.apache.commons.geometry.euclidean.twod.PolygonsSet;
import org.apache.commons.geometry.euclidean.twod.Vector2D;

/** This class creates simple OBJ files from {@link PolyhedronsSet} instances.
 * The output files can be opened in a 3D viewer for visual debugging of 3D
 * regions. This class is only intended for use in testing.
 *
 * @see https://en.wikipedia.org/wiki/Wavefront_.obj_file
 */
public class OBJWriter {

    /** Writes an OBJ file representing the given {@link PolyhedronsSet}. Only
     * finite boundaries are written. Infinite boundaries are ignored.
     * @param file The path of the file to write
     * @param poly The input PolyhedronsSet
     * @throws IOException
     */
    public static void write(String file, PolyhedronsSet poly) throws IOException {
        write(new File(file), poly);
    }

    /** Writes an OBJ file representing the given {@link PolyhedronsSet}. Only
     * finite boundaries are written. Infinite boundaries are ignored.
     * @param file The file to write
     * @param poly The input PolyhedronsSet
     * @throws IOException
     */
    public static void write(File file, PolyhedronsSet poly) throws IOException {
        // get the vertices and faces
        MeshBuilder meshBuilder = new MeshBuilder(poly.getPrecision());
        poly.getTree(true).visit(meshBuilder);

        // write them to the file
        try (Writer writer = Files.newBufferedWriter(file.toPath())) {
            writer.write("# Generated by " + OBJWriter.class.getName() + " on " + new Date() + "\n");
            writeVertices(writer, meshBuilder.getVertices());
            writeFaces(writer, meshBuilder.getFaces());
        }
    }

    /** Writes the given list of vertices to the file in the OBJ format.
     * @param writer
     * @param vertices
     * @throws IOException
     */
    private static void writeVertices(Writer writer, List<Vector3D> vertices) throws IOException {
        DecimalFormat df = new DecimalFormat("0.######");

        for (Vector3D v : vertices) {
            writer.write("v ");
            writer.write(df.format(v.getX()));
            writer.write(" ");
            writer.write(df.format(v.getY()));
            writer.write(" ");
            writer.write(df.format(v.getZ()));
            writer.write("\n");
        }
    }

    /** Writes the given list of face vertex indices to the file in the OBJ format. The indices
     * are expected to be 0-based and are converted to the 1-based format used by OBJ.
     * @param writer
     * @param faces
     * @throws IOException
     */
    private static void writeFaces(Writer writer, List<int[]> faces) throws IOException {
        for (int[] face : faces) {
            writer.write("f ");
            for (int idx : face) {
                writer.write(String.valueOf(idx + 1)); // obj indices are 1-based
                writer.write(" ");
            }
            writer.write("\n");
        }
    }

    /** Class used to impose a strict sorting on 3D vertices.
     * If all of the components of two vertices are within tolerance of each
     * other, then the vertices are considered equal. This helps to avoid
     * writing duplicate vertices in the OBJ output.
     */
    private static class VertexComparator implements Comparator<Vector3D> {

        /** Precision context to deteremine floating-point equality */
        private final DoublePrecisionContext precision;

        /** Creates a new instance with the given tolerance value.
         * @param tolerance
         */
        public VertexComparator(final DoublePrecisionContext precision) {
            this.precision = precision;
        }

        /** {@inheritDoc} */
        @Override
        public int compare(Vector3D a, Vector3D b) {
            int result = precision.compare(a.getX(), b.getX());
            if (result == 0) {
                result = precision.compare(a.getY(), b.getY());
                if (result == 0) {
                    result = precision.compare(a.getZ(), b.getZ());
                }
            }
            return result;
        }
    }

    /** Class for converting a 3D BSPTree into a list of vertices
     * and face vertex indices.
     */
    private static class MeshBuilder implements BSPTreeVisitor<Vector3D> {

        /** Precision context to deteremine floating-point equality */
        private final DoublePrecisionContext precision;

        /** Map of vertices to their index in the vertices list */
        private Map<Vector3D, Integer> vertexIndexMap;

        /** List of unique vertices in the BSPTree boundary */
        private List<Vector3D> vertices;

        /**
         * List of face vertex indices. Each face will have 3 indices. Indices
         * are 0-based.
         * */
        private List<int[]> faces;

        /** Creates a new instance with the given tolerance.
         * @param tolerance
         */
        public MeshBuilder(final DoublePrecisionContext precision) {
            this.precision = precision;
            this.vertexIndexMap = new TreeMap<>(new VertexComparator(precision));
            this.vertices = new ArrayList<>();
            this.faces = new ArrayList<>();
        }

        /** Returns the list of unique vertices found in the BSPTree.
         * @return
         */
        public List<Vector3D> getVertices() {
            return vertices;
        }

        /** Returns the list of 0-based face vertex indices for the BSPTree. Each face is
         * a triangle with 3 indices.
         * @return
         */
        public List<int[]> getFaces() {
            return faces;
        }

        /** {@inheritDoc} */
        @Override
        public Order visitOrder(BSPTree<Vector3D> node) {
            return Order.SUB_MINUS_PLUS;
        }

        /** {@inheritDoc} */
        @SuppressWarnings("unchecked")
        @Override
        public void visitInternalNode(BSPTree<Vector3D> node) {
            BoundaryAttribute<Vector3D> attr = (BoundaryAttribute<Vector3D>) node.getAttribute();

            if (attr.getPlusOutside() != null) {
                addBoundary((SubPlane) attr.getPlusOutside());
            }
            else if (attr.getPlusInside() != null) {
                addBoundary((SubPlane) attr.getPlusInside());
            }
        }

        /** {@inheritDoc} */
        @Override
        public void visitLeafNode(BSPTree<Vector3D> node) {
            // do nothing
        }

        /** Adds the region boundary defined by the given {@link SubPlane}
         * to the mesh.
         * @param subplane
         */
        private void addBoundary(SubPlane subplane) {
            Plane plane = (Plane) subplane.getHyperplane();
            PolygonsSet poly = (PolygonsSet) subplane.getRemainingRegion();

            TriangleExtractor triExtractor = new TriangleExtractor(precision);
            poly.getTree(true).visit(triExtractor);

            Vector3D v1, v2, v3;
            for (Vector2D[] tri : triExtractor.getTriangles()) {
                v1 = plane.toSpace(tri[0]);
                v2 = plane.toSpace(tri[1]);
                v3 = plane.toSpace(tri[2]);

                faces.add(new int[] {
                        getVertexIndex(v1),
                        getVertexIndex(v2),
                        getVertexIndex(v3)
                });
            }
        }

        /** Returns the 0-based index of the given vertex in the <code>vertices</code>
         * list. If the vertex has not been encountered before, it is added
         * to the list.
         * @param vertex
         * @return
         */
        private int getVertexIndex(Vector3D vertex) {
            Integer idx = vertexIndexMap.get(vertex);
            if (idx == null) {
                idx = vertices.size();

                vertices.add(vertex);
                vertexIndexMap.put(vertex, idx);
            }
            return idx.intValue();
        }
    }

    /** Visitor for extracting a collection of triangles from a 2D BSPTree.
     */
    private static class TriangleExtractor implements BSPTreeVisitor<Vector2D> {

        /** Precision context to deteremine floating-point equality */
        private final DoublePrecisionContext precision;

        /** List of extracted triangles */
        private List<Vector2D[]> triangles = new ArrayList<>();

        /** Creates a new instance with the given geometric tolerance.
         * @param tolerance
         */
        public TriangleExtractor(final DoublePrecisionContext precision) {
            this.precision = precision;
        }

        /** Returns the list of extracted triangles.
         * @return
         */
        public List<Vector2D[]> getTriangles() {
            return triangles;
        }

        /** {@inheritDoc} */
        @Override
        public Order visitOrder(BSPTree<Vector2D> node) {
            return Order.SUB_MINUS_PLUS;
        }

        /** {@inheritDoc} */
        @Override
        public void visitInternalNode(BSPTree<Vector2D> node) {
            // do nothing
        }

        /** {@inheritDoc} */
        @Override
        public void visitLeafNode(BSPTree<Vector2D> node) {
            if ((Boolean) node.getAttribute()) {
                PolygonsSet convexPoly = new PolygonsSet(node.pruneAroundConvexCell(Boolean.TRUE,
                        Boolean.FALSE, null), precision);

                for (Vector2D[] loop : convexPoly.getVertices()) {
                    if (loop.length > 0 && loop[0] != null) { // skip unclosed loops
                        addTriangles(loop);
                    }
                }
            }
        }

        /** Splits the 2D convex area defined by the given vertices into
         * triangles and adds them to the internal list.
         * @param vertices
         */
        private void addTriangles(Vector2D[] vertices) {
            // use a triangle fan to add the convex region
            for (int i=2; i<vertices.length; ++i) {
                triangles.add(new Vector2D[] { vertices[0], vertices[i-1], vertices[i] });
            }
        }
    }
}
