import React, { useEffect } from "react";
import {
  DirectionalLight,
  Object3D,
  PerspectiveCamera,
  Scene,
  WebGLRenderer,
  AmbientLight,
  Vector3,
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import CSS from "csstype";
 
import { useParams } from "react-router-dom";
import { HttpMethod, HttpRepository, HttpRoute } from "../../core/repository/http_repository";

const canvasStyle: CSS.Properties = {
  backgroundColor: "rgb(151 41 41 / 85%)",
};

export interface AssemblyPreviewStructure {
  assembly: string[];
  offset: number;
  count: number;
}

export const AssemblyPreviewSubsequencePath = "/123/";

export const AssemblyPreviewSubsequence = () => {
  const container = new Object3D();
  const canvasRef = React.useRef<HTMLCanvasElement>(null);
  const scene = new Scene();
  const camera = new PerspectiveCamera(
    80,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  let renderId = 1;
  let assemblyCounter: undefined | Number = undefined;
  let params = useParams().id;

  useEffect(() => {
    const renderer = new WebGLRenderer({
      canvas: canvasRef.current as HTMLCanvasElement,
      antialias: true,
      alpha: true,
    });

    camera.position.set(2, 1, 2);

    const directionalLight = new DirectionalLight(0xffffff, 0.2);
    directionalLight.castShadow = true;
    directionalLight.position.set(-1, 2, 4);
    scene.add(directionalLight);

    const ambientLight = new AmbientLight(0xffffff, 0.7);
    scene.add(ambientLight);
    container.position.set(0, 0, 0);

    renderer.setSize(window.innerWidth, window.innerHeight);

    const onResize = () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer!.setSize(window.innerWidth, window.innerHeight);
    };

    window.addEventListener("resize", onResize, false);
    new OrbitControls(camera, renderer.domElement);

    renderer!.setAnimationLoop(() => {
      renderer!.render(scene, camera);
    });
    renderObject(1, params!);
  } );

  async function renderObject(renderId: Number,projectId:string ) {
    const assemblyResponse =
      await HttpRepository.jsonRequest<AssemblyPreviewStructure>(
        HttpMethod.GET,
        `${HttpRoute.assemblyPreviewPath}${projectId}?count=${renderId}`
      );
    assemblyCounter = assemblyResponse.count;

    loadObject(assemblyResponse.assembly);
  }

  async function click() {
    renderId = renderId + 1;
    console.log(assemblyCounter);
    console.log(renderId);
    if (assemblyCounter === renderId) {
      renderId = 1;
    }
    renderObject(renderId, params!);
  }

  function loadObject(objectList: string[]) {
    objectList.forEach((el) => {
      const fbxLoader = new OBJLoader();
      fbxLoader.load(
        el,
        (object) => {
          object.scale.x = 0.3;
          object.scale.y = 0.3;
          object.scale.z = 0.3;
          object.rotation.x = -Math.PI / 2;
          object.position.y = -30;
          container.add(object);
          scene.add(container);

          fitCameraToCenteredObject(camera, container);
        },
        (xhr) => {
          console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
        },
        (error) => {
          console.log(error);
        }
      );
    });
  }
  function fitCameraToCenteredObject(
    camera: PerspectiveCamera,
    object: Object3D
  ) {
    const dist = 50;
    const vector = new Vector3();

    camera.getWorldDirection(vector);

    vector.multiplyScalar(dist);
    vector.add(camera.position);

    object.position.set(vector.x, vector.y, vector.z);
    object.setRotationFromQuaternion(camera.quaternion);
  }
  return <canvas onClick={() => click()} style={canvasStyle} ref={canvasRef} />;
};
