<script lang="ts">
  import { createEventDispatcher, onMount } from "svelte";
  const dispatch = createEventDispatcher();

  export let src: string;
  export let lookonly = false;

  let root: HTMLElement;

  onMount(async () => {
    root.style.height = `${root.clientWidth}px`;

    const THREE = await import("three");
    const THREE_OC = await import("three/examples/jsm/controls/OrbitControls");
    const THREE_STL = await import("three/examples/jsm/loaders/STLLoader");

    const camera = new THREE.PerspectiveCamera(
      70,
      root.clientWidth / root.clientHeight
    );

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setSize(root.clientWidth, root.clientHeight);
    root.appendChild(renderer.domElement);

    const controls = new THREE_OC.OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.1;
    controls.enableZoom = true;
    controls.autoRotate = true;
    controls.autoRotateSpeed = 3;

    const scene = new THREE.Scene();
    scene.add(new THREE.HemisphereLight(0xffffff, 1.5));

    const loader = new THREE_STL.STLLoader();
    loader.load(src, (geometry) => {
      const material = new THREE.MeshPhongMaterial({
        color: 0xdc322f,
        specular: 100,
        shininess: 70,
      });
      const mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);

      const middle = new THREE.Vector3();
      geometry.computeBoundingBox();
      geometry.boundingBox.getCenter(middle);
      mesh.geometry.applyMatrix4(
        new THREE.Matrix4().makeTranslation(-middle.x, -middle.y, -middle.z)
      );
      mesh.geometry.applyMatrix4(
        new THREE.Matrix4().makeRotationX(-Math.PI / 2)
      );

      const largestDimension = Math.max(
        geometry.boundingBox.max.x,
        geometry.boundingBox.max.y,
        geometry.boundingBox.max.z
      );
      camera.position.z = largestDimension * 2;
    });

    function animate() {
      controls.update();
      renderer.render(scene, camera);
      requestAnimationFrame(animate);
    }
    animate();

    dispatch("loaded");
  });
</script>

<div class="modelviewer" class:lookonly bind:this={root} />

<style>
  .modelviewer {
    width: 100%;
  }

  .modelviewer.lookonly {
    pointer-events: none;
  }
</style>
