import { Mesh } from '../../mesh'
import { Texture } from '../../mesh/material'

import { mat4 } from 'gl-matrix'

import Resource from '../../resource'

const FNAMES = ['right', 'left', 'top', 'bottom', 'back', 'front']
const SIZE = 500

class Skybox {
  constructor (name, size = SIZE) {
    this.name = name
    this.size = size
  }

  async initialize (gl) {
    await this.createTexture(gl)
    this.createMesh(gl)
  }

  async createTexture (gl) {
    let ready = []
    for (let i in FNAMES) {
      let real = this.name + '/' + FNAMES[i] + '.png'
      let loaded = await Resource.loadImage(real)
      ready[i] = loaded
    }

    let imgCube = Texture.createTextureCubeMap(gl, ready)
    this.cubemap = imgCube
  }

  createMesh (gl) {
    const vertices = [
      -this.size, this.size, -this.size,
      -this.size, -this.size, -this.size,
      this.size, -this.size, -this.size,
      this.size, -this.size, -this.size,
      this.size, this.size, -this.size,
      -this.size, this.size, -this.size,

      -this.size, -this.size, this.size,
      -this.size, -this.size, -this.size,
      -this.size, this.size, -this.size,
      -this.size, this.size, -this.size,
      -this.size, this.size, this.size,
      -this.size, -this.size, this.size,

      this.size, -this.size, -this.size,
      this.size, -this.size, this.size,
      this.size, this.size, this.size,
      this.size, this.size, this.size,
      this.size, this.size, -this.size,
      this.size, -this.size, -this.size,

      -this.size, -this.size, this.size,
      -this.size, this.size, this.size,
      this.size, this.size, this.size,
      this.size, this.size, this.size,
      this.size, -this.size, this.size,
      -this.size, -this.size, this.size,

      -this.size, this.size, -this.size,
      this.size, this.size, -this.size,
      this.size, this.size, this.size,
      this.size, this.size, this.size,
      -this.size, this.size, this.size,
      -this.size, this.size, -this.size,

      -this.size, -this.size, -this.size,
      -this.size, -this.size, this.size,
      this.size, -this.size, -this.size,
      this.size, -this.size, -this.size,
      -this.size, -this.size, this.size,
      this.size, -this.size, this.size
    ]
    this.mesh = Mesh.constructFromVertices(gl, vertices)
  }

  updateCamera (gl, shader, camera) {
    const projloc = shader.getUniformLocation(gl, 'uProjectionMatrix')
    const viewloc = shader.getUniformLocation(gl, 'uViewMatrix')

    // Set translation to zero to prevent the skybox from moving in relation to the camera
    let view = mat4.clone(camera.view)
    view[12] = 0
    view[13] = 0
    view[14] = 0

    gl.uniformMatrix4fv(projloc, false, camera.projection)
    gl.uniformMatrix4fv(viewloc, false, view)
  }

  draw (gl, shader, camera) {
    camera && this.updateCamera(gl, shader, camera)

    gl.activeTexture(gl.TEXTURE0)
    gl.bindTexture(this.cubemap.type, this.cubemap.id)
    this.mesh.prepare(gl, shader)
    this.mesh.draw(gl, shader)
    this.mesh.postdraw(gl, shader)
  }
}

export { Skybox }
