import {
    AmbientLight as ThreeAmbientLight,
    Box3,
    DirectionalLight as ThreeDirectionalLight,
    PerspectiveCamera as ThreePerspectiveCamera,
    Scene as ThreeScene,
    Vector3 as ThreeVector3
} from "three";
import Vector3 from "../../../core/geom/Vector3.js";
import { rootObject3DFastMatrixUpdate } from "../ecs/mesh/rootObject3DFastMatrixUpdate.js";
import { camera_compute_distance_to_fit_length } from "../camera/camera_compute_distance_to_fit_length.js";
import { scaleObject3ToBox } from "./ScaleObject3ToBox.js";
import { DEG_TO_RAD } from "../../../core/math/DEG_TO_RAD.js";
import AABB2 from "../../../core/geom/2d/aabb/AABB2.js";

/**
 *
 * @param {THREE.OrthographicCamera} camera
 */
function setShadowCamera(camera) {
    const sqrt2 = Math.sqrt(2);
    let sqrt2_2 = sqrt2 / 2;
    camera.left = -sqrt2_2;
    camera.right = sqrt2_2;

    camera.bottom = -sqrt2_2;
    camera.top = sqrt2_2;
}

/**
 *
 * @param {THREE.Scene} scene
 */
function setupLights(scene) {
    const lightKey = new ThreeDirectionalLight(0xffffff, 1);
    lightKey.position.set(-1, 1, 1);
    lightKey.castShadow = true;
    lightKey.shadow.mapSize.set(1024, 1024);


    setShadowCamera(lightKey.shadow.camera);
    scene.add(lightKey);

    const lightHighlight = new ThreeDirectionalLight(0xffffff, 0.50);
    lightHighlight.position.set(0, 0, 1);
    scene.add(lightHighlight);

    const lightFill = new ThreeAmbientLight(0xFFFFFF, 0.5);
    scene.add(lightFill);
}

/**
 *
 * @param {Mesh} mesh trhee.js mesh
 * @param {Vector2} size
 * @param {AABB2} focus
 * @returns {{scene: Scene, camera: THREE.PerspectiveCamera}}
 */
export function makeMeshPreviewScene(mesh, size, focus = new AABB2(0, 0, size.x, size.y)) {
    const scene = new ThreeScene();

    setupLights(scene);

    scaleObject3ToBox(mesh, new Vector3(1, 1, 1), mesh.scale);
    scene.add(mesh);


    const camera = new ThreePerspectiveCamera(45, size.x / size.y, 0.1, 10);

    const bBox = new Box3();

    bBox.expandByObject(mesh);

    const bBoxCenterScaled = new Vector3();
    bBoxCenterScaled.copy(bBox.min).add(bBox.max).multiplyScalar(0.5);

    //center model at 0,0,0
    mesh.position.set(0, 0, 0).sub(bBoxCenterScaled);
    //update transformation matrix
    rootObject3DFastMatrixUpdate(mesh);
    //move model to align front of BB with z=0

    const focusHeight = (focus.y1 - focus.y0);


    const fov = camera.fov * DEG_TO_RAD;
    const distance = bBox.max.z + camera_compute_distance_to_fit_length(focusHeight, fov);

    const cameraPositionX = focus.x0 + (focus.x1 - focus.x0) / 2 - 0.5;
    const cameraPositionY = 0.5 - (focus.y0 + (focus.y1 - focus.y0) / 2);
    camera.position.set(cameraPositionX, cameraPositionY, distance);
    camera.lookAt(new ThreeVector3(cameraPositionX, cameraPositionY, 0));


    //set near and far for camera to capture
    // camera.near = 0.1;
    // camera.far = bBox.size.z * mesh.scale.z+distance;

    return { scene: scene, camera: camera };
}
