import { Camera, Color, Geometry, GLTFLoader, Mesh, Program, Renderer, Transform } from 'ogl';
import { rand, randMinMax } from "./random";

import fragment from "./Leaf.frag";
import vertex from "./Leaf.vert";

let rotation = 0;

export function setRotation(r: number) {
  rotation = r;
}

export function createLeaves({ canvas, num = 20, color, minZ = -1, maxZ = 1 }: { canvas: HTMLCanvasElement, num?: number, color?: Color, minZ?: number, maxZ?: number }) {


  const renderer = new Renderer({ dpr: 1, canvas, alpha: true });
  const gl = renderer.gl;


  const camera = new Camera(gl, { fov: 15 });
  camera.position.z = 5;

  function resize() {
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.perspective({ aspect: gl.canvas.width / gl.canvas.height });
  }
  window.addEventListener('resize', resize, false);
  resize();

  const scene = new Transform();

  const program = new Program(gl, {
    vertex,
    fragment,
    cullFace: gl.NONE,
    depthTest: true,
    uniforms: {
      uTime: { value: 0 },
      uRot: { value: 0 },
      uBackground: { value: color },
    },
  });

  let mesh: Mesh;
  loadModel();
  async function loadModel() {

    const model = await GLTFLoader.load(gl, "/models/leaf.glb");

    // @ts-ignore
    const data = model.nodes[0].children[0].geometry.attributes;

    let offset = new Float32Array(num * 3);
    let random = new Float32Array(num * 3);
    for (let i = 0; i < num; i++) {
      offset.set([rand(8), rand(4), randMinMax(minZ, maxZ)], i * 3);

      // unique random values are always handy for instances.
      // Here they will be used for rotation, scale and movement.
      random.set([Math.random(), Math.random(), Math.random()], i * 3);
    }

    const geometry = new Geometry(gl, {
      ...data,

      // simply add the 'instanced' property to flag as an instanced attribute.
      // set the value as the divisor number
      offset: { instanced: 1, size: 3, data: offset },
      random: { instanced: 1, size: 3, data: random },
    });

    mesh = new Mesh(gl, { geometry, program });
    mesh.scale.set(0.2, 0.2, 0.2)
    mesh.setParent(scene);
  }

  requestAnimationFrame(update);
  function update(t: number) {
    requestAnimationFrame(update);

    program.uniforms.uTime.value = t * 0.001;
    program.uniforms.uRot.value = rotation;
    renderer.render({ scene, camera });
  }

}
