import Engine from './engine'
import Camera from './engine/camera'
import loadMesh from './engine/mesh/loader'

import { Environment } from './engine/environment'
import { Terrain } from './engine/components/terrain'
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
import { Material } from './engine/mesh/material'

import { CubePlanet } from './engine/components/planet'

let game = new Engine()
let env = new Environment()

// let t = 0
async function pipeline () {
  let entity = await loadMesh(game.gl, 'test')
  let shader = await game.shaders.createShaderFromFiles(game.gl, 'basic', false)
  let terrainShader = await game.shaders.createShaderFromFiles(game.gl, 'terrain', false)

  entity.setRotation([0.0, 0.0, -90.0])

  // Create a height map based on OpenSimplex noise
  let hmap = new SimplexHeightMap(1, 1, 256, 50)

  // Create a terrain
  let terrain = new Terrain([0.0, 0.0, 0.0], 256, 256)
  terrain.createMesh(game.gl, hmap)

  // Terrain material
  let material = new Material()
  material.textures = ['grass-1024.jpg']
  await material.loadTextures(game.gl)
  terrain.setMaterial(material)

  // Create and initialize the camera
  let cam = new Camera([-100.0, 1.0, 0.0])
  cam.updateProjection(game.gl)

  // Planet test
  let planet = new CubePlanet([0.0, 0.0, 0.0], 16, 32)

  // Update function for camera
  game.addUpdateFunction(function (dt) {
    if (game.input.isDown('w')) {
      cam.processKeyboard(0, dt)
    } else if (game.input.isDown('s')) {
      cam.processKeyboard(1, dt)
    }

    if (game.input.isDown('a')) {
      cam.processKeyboard(2, dt)
    } else if (game.input.isDown('d')) {
      cam.processKeyboard(3, dt)
    }

    if (game.input.mouseMoved && game.input.mouse.btn0) {
      cam.processMouseMove(game.input.mouseOffset)
    }

    // TESTING: Move model forward
    // t = t + 0.1
    // entity.setPosition([t, 0.0, 0.0])
  })

  // Render function for the triangle
  game.addRenderFunction(function (gl) {
    shader.use(gl)
    cam.draw(gl, shader)
    entity.draw(gl, shader)
    planet.draw(gl, shader)

    // Use terrain shader
    terrainShader.use(gl)

    // Set environment variables in shader
    env.draw(gl, terrainShader)

    // Set the viewport uniforms
    cam.draw(gl, terrainShader)

    // Draw terrain
    terrain.draw(gl, terrainShader)
  })

  game.startGameLoop()
}

// Start the game, catch any errors thrown
pipeline().catch(function (e) {
  console.error(e)
})
