import {
  Scene,
  PerspectiveCamera,
  WebGLRenderer,
  DirectionalLight,
  AmbientLight,
  Mesh,
  Clock,
  BoxGeometry,
  MeshToonMaterial,
} from 'three';

export class Renderer {
  public scene!: Scene;
  public camera!: PerspectiveCamera;
  public renderer!: WebGLRenderer;

  public sun!: DirectionalLight;
  public ambient!: AmbientLight;

  public ground!: Mesh;

  private clock = new Clock();
  private _updateFn?: (dt: number) => void;

  constructor() {}

  get canvas() {
    return this.renderer.domElement;
  }

  initialize() {
    this.scene = new Scene();
    this.camera = new PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000,
    );

    this.renderer = new WebGLRenderer();
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(this.renderer.domElement);

    this.renderer.setClearColor(0x00ddff);

    this.sun = new DirectionalLight(0xffffff);
    this.sun.position.set(10, 10, 0);
    this.scene.add(this.sun);

    this.ambient = new AmbientLight(0xffffff, 0.5);
    this.scene.add(this.ambient);

    this.ground = new Mesh(
      new BoxGeometry(100, 1, 100, 10, 1, 10),
      new MeshToonMaterial({ color: 0x32a852 }),
    );

    this.ground.position.set(0, -0.5, 0);
    //this.scene.add(this.ground);

    this.camera.position.set(0, 4, 4);

    window.addEventListener('resize', () => {
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
    });

    this.render();
  }

  render() {
    requestAnimationFrame(() => this.render());

    const delta = this.clock.getDelta();
    if (this._updateFn) {
      this._updateFn(delta);
    }

    this.renderer.render(this.scene, this.camera);
  }

  public registerUpdateFunction(fn: (dt: number) => void) {
    this._updateFn = fn;
  }
}
