import { LineBasicMaterial } from "three";
import Entity from "../../../../engine/ecs/Entity.js";
import { Transform } from "../../../../engine/ecs/transform/Transform.js";
import { EngineHarness } from "../../../../engine/EngineHarness.js";
import { DrawMode } from "../../../../engine/graphics/ecs/mesh-v2/DrawMode.js";
import { ShadedGeometry } from "../../../../engine/graphics/ecs/mesh-v2/ShadedGeometry.js";
import { ShadedGeometrySystem } from "../../../../engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
import { Gizmo } from "../../../../engine/graphics/render/gizmo/Gizmo.js";
import { GizmoRenderingPlugin } from "../../../../engine/graphics/render/gizmo/GizmoRenderingPlugin.js";
import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
import { seededRandom } from "../../../math/random/seededRandom.js";
import { number_pretty_print } from "../../../primitives/numbers/number_pretty_print.js";
import { delay } from "../../../process/delay.js";
import { AABB3 } from "../aabb/AABB3.js";
import { make_justified_point_grid } from "../util/make_justified_point_grid.js";
import { compute_delaunay_tetrahedral_mesh } from "./delaunay/compute_delaunay_tetrahedral_mesh.js";
import { tetrahedral_mesh_build_from_grid } from "./delaunay/grid/tetrahedral_mesh_build_from_grid.js";
import { build_tetrahedral_mesh_buffer_geometry } from "./graphics/build_tetrahedral_mesh_buffer_geometry.js";
import { TetrahedralMesh } from "./TetrahedralMesh.js";


/**
 *
 * @param {TetrahedralMesh} tetrahedra
 * @param {number[]} points
 */
function make_delaunay_grid(tetrahedra, points) {

    const random = seededRandom();

    for (let i = 0; i < 600; i++) {
        points.push(
            randomFloatBetween(random, -100, 100),
            randomFloatBetween(random, 0, 150),
            randomFloatBetween(random, -100, 100),
        );
    }

    make_justified_point_grid(
        new AABB3(-100, 0, -100, 100, 150, 100),
        20,
        (x, y, z) => {
            points.push(x, y, z);
        }
    );

    compute_delaunay_tetrahedral_mesh(tetrahedra, points, points.length / 3);
}

/**
 *
 * @param {Engine} engine
 * @return {Promise<void>}
 */
async function main(engine) {
    await EngineHarness.buildBasics({
        engine,
        enableWater: false
    });

    const offset = [7.5, 1, 7.5];
    const scale = [.5, .5, .5];

    /**
     *
     * @type {number[]}
     */
    const points = [];

    const tetrahedra = new TetrahedralMesh();

    await delay(1000);

    console.time('mesh build');
    tetrahedral_mesh_build_from_grid(
        tetrahedra,
        points,
        new AABB3(-10, 0, -10, 10, 10, 10),
        4, 4, 4
    )
    console.timeEnd('mesh build');
    console.log(`Mesh build for ${number_pretty_print(points.length / 3)} points`)

    console.log(tetrahedra);

    await delay(500);

    const relocated_elements = tetrahedra.compact();
    console.log(`Compaction relocated ${relocated_elements} elements`);

    const geometry = build_tetrahedral_mesh_buffer_geometry(tetrahedra, points);


    new Entity()
        .add(ShadedGeometry.from(geometry, new LineBasicMaterial({ color: 0xFF0000 }), DrawMode.LineSegments))
        .add(Transform.fromJSON({
            position: { x: offset[0], y: offset[1], z: offset[2] },
            scale: { x: scale[0], y: scale[1], z: scale[2] },
        }))
        .build(engine.entityManager.dataset);

    engine.graphics.on.preRender.add(() => {

        Gizmo.color = [1, 1, 1, 1];

        const point_count = points.length;

        for (let i = 0; i < point_count; i += 3) {

            Gizmo.draw_solid_sphere([
                points[i] * scale[0] + offset[0],
                points[i + 1] * scale[1] + offset[1],
                points[i + 2] * scale[2] + offset[2]
            ], 0.1);
        }
    });
}

new EngineHarness().initialize({
    configuration(config, engine) {
        config.addSystem(new ShadedGeometrySystem(engine));
        config.addPlugin(GizmoRenderingPlugin);
    }
}).then(main);
