import { initializeEditor } from "../../../../../../../model/game/initializeEditor.js";
import { enableEditor } from "../../../../../../editor/enableEditor.js";
import { AABB3 } from "../../../../../core/geom/3d/aabb/AABB3.js";
import Quaternion from "../../../../../core/geom/Quaternion.js";
import Vector2 from "../../../../../core/geom/Vector2.js";
import Vector3 from "../../../../../core/geom/Vector3.js";
import { randomFloatBetween } from "../../../../../core/math/random/randomFloatBetween.js";
import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
import { GameAssetType } from "../../../../asset/GameAssetType.js";
import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
import Entity from "../../../../ecs/Entity.js";
import { TransformAttachmentSystem } from "../../../../ecs/transform-attachment/TransformAttachmentSystem.js";
import { Transform } from "../../../../ecs/transform/Transform.js";
import { EngineHarness } from "../../../../EngineHarness.js";
import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
import { OrbitingBehavior } from "../../../../intelligence/behavior/ecs/OrbitingBehavior.js";
import Highlight from "../../highlight/Highlight.js";
import { ShadedGeometryHighlightSystem } from "../../highlight/system/ShadedGeometryHighlightSystem.js";
import { MeshSystem } from "../../mesh/MeshSystem.js";
import { ShadedGeometry } from "../ShadedGeometry.js";
import { ShadedGeometrySystem } from "../ShadedGeometrySystem.js";
import { SGMesh } from "./SGMesh.js";
import { SGMeshEvents } from "./SGMeshEvents.js";
import { SGMeshHighlightSystem } from "./SGMeshHighlightSystem.js";
import { SGMeshSystem } from "./SGMeshSystem.js";

new EngineHarness().initialize({
    configuration(config, engine) {
        config.addManySystems(
            new ShadedGeometrySystem(engine),
            new SGMeshSystem(engine),
            new BehaviorSystem(engine),
            new MeshSystem(engine),
            new TransformAttachmentSystem(),
            new SGMeshHighlightSystem(),
            new ShadedGeometryHighlightSystem(engine)
        );

        // config.addPlugin(GizmoRenderingPlugin);
        // config.addPlugin(MicronRenderPlugin);

        const gltfAssetLoader = new GLTFAssetLoader();

        config.addLoader(GameAssetType.ModelGLTF_JSON, gltfAssetLoader);
        config.addLoader(GameAssetType.ModelGLTF, gltfAssetLoader);
    }
}).then(main);

/**
 *
 * @param {EntityComponentDataset} ecd
 * @param {Engine} engine
 */
function make_grid(ecd, engine) {
    const random = seededRandom(1);

    const GRID_SIZE = 40;
    const GRID_FREQUENCY_SIZE = 7;

    for (let i = 0; i < GRID_SIZE; i++) {
        for (let j = 0; j < GRID_SIZE; j++) {
            const quaternion = new Quaternion();

            quaternion.fromEulerAnglesXYZ(0, random() * Math.PI, 0);

            const center = new Vector3(i * 8, 0, j * 8);

            const transform = Transform.fromJSON({
                position: center,
                rotation: quaternion,
                scale: randomFloatBetween(random, 0.5, 2)
            });

            const orbitingBehavior = OrbitingBehavior.from({
                center: center,
                rate: 1,
                radius: 5
            });

            // const ctx = {
            //     time: Math.sin(i * Math.PI / (GRID_FREQUENCY_SIZE - 1)) + Math.cos(j * Math.PI / (GRID_FREQUENCY_SIZE - 1))
            // };
            //
            // const color = [random(), random(), random(), 1];

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

                const bounds = new AABB3();
                mesh.getUntransformedBoundingBox(bounds);
                bounds.applyMatrix4(transform.matrix);

                // mesh.getBoundingBox(bounds);

                // Gizmo.color = color;
                //
                // Gizmo.draw_wire_cube(
                //     [
                //         bounds.getCenterX(), bounds.getCenterY(), bounds.getCenterZ()
                //     ],
                //     [
                //         bounds.getExtentsX(), bounds.getExtentsY(), bounds.getExtentsZ()
                //     ]
                // );
            });


            const mesh = SGMesh.fromURL("data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf");
            // const mesh = SGMesh.fromURL("data/models/samples/transform-hierarchy.glb");
            new Entity()
                .add(mesh)
                .add(transform)
                .add(BehaviorComponent.from(
                    orbitingBehavior
                    // RepeatBehavior.from(
                    //     new ActionBehavior((t) => {
                    //         ctx.time += t;
                    //
                    //         const f = smoothStep(0, 1, pingpong(ctx.time / 2.5, 1));
                    //
                    //         transform.position.set(center.x, center.y + f * 5, center.z);
                    //
                    //     })
                    // )
                ))
                .build(ecd);
        }
    }
}

/**
 *
 * @param {Engine} engine
 */
function main(engine) {
    EngineHarness.buildBasics({
        engine,
        terrainResolution: 1,
        terrainSize: new Vector2(100, 100)
    });

    enableEditor(engine, initializeEditor);

    const ecd = engine.entityManager.dataset;

    // const mesh = SGMesh.fromURL("data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf");
    // const mesh = SGMesh.fromURL("moicon/ztest_object_many_pieces/model.gltf");
    const mesh = SGMesh.fromURL("moicon/2022_04_20__Micron_from_Philippe/model.gltf");
    // const mesh = Mesh.fromURL("moicon/ztest_object_many_pieces/model.gltf");

    new Entity()
        .add(Transform.fromJSON({
            position: new Vector3(10, 0, 10)
        }))
        .add(Highlight.fromOne(1, 0, 0, 1))
        .add(mesh)
        /*   .add(BehaviorComponent.fromOne(OrbitingBehavior.from({
               center: new Vector3(10, 0, 10),
               radius: 5,
               rate: 2
           })))*/
        .addEventListener(SGMeshEvents.AssetLoaded, () => {
            mesh.__node.traverse(n => {
                /**
                 *
                 * @type {ShadedGeometry}
                 */
                const sg = n.entity.getComponent(ShadedGeometry);

                if (sg !== null) {
                    sg.draw_method = 1;
                }
            });
        })
    // .build(ecd);

    make_grid(ecd, engine);
}
