import { Node } from '../'
import { Mesh } from '../../mesh'

class Terrain extends Node {
  constructor (pos, sWidth, sHeight) {
    super(pos)

    this.width = sWidth
    this.height = sHeight

    this.mesh = null
  }

  createMesh (gl, heightMap) {
    let VERTICES = heightMap.size
    let count = VERTICES * VERTICES
    let vertices = new Array(count * 3)
    let normals = new Array(count * 3)
    let textureCoords = new Array(count * 2)
    let indices = new Array(6 * (VERTICES - 1) * (VERTICES - 1))
    let vertexPointer = 0

    for (let i = 0; i < VERTICES; i++) {
      for (let j = 0; j < VERTICES; j++) {
        vertices[vertexPointer * 3] = j / (VERTICES - 1) * this.width
        vertices[vertexPointer * 3 + 1] = heightMap.getHeight(j, i)
        vertices[vertexPointer * 3 + 2] = i / (VERTICES - 1) * this.height
        let normal = heightMap.getNormal(j, i)
        normals[vertexPointer * 3] = normal[0]
        normals[vertexPointer * 3 + 1] = normal[1]
        normals[vertexPointer * 3 + 2] = normal[2]
        textureCoords[vertexPointer * 2] = j / (VERTICES - 1)
        textureCoords[vertexPointer * 2 + 1] = i / (VERTICES - 1)
        vertexPointer++
      }
    }

    let pointer = 0
    for (let gz = 0; gz < VERTICES - 1; gz++) {
      for (let gx = 0; gx < VERTICES - 1; gx++) {
        let topLeft = (gz * VERTICES) + gx
        let topRight = topLeft + 1
        let bottomLeft = ((gz + 1) * VERTICES) + gx
        let bottomRight = bottomLeft + 1
        indices[pointer++] = topLeft
        indices[pointer++] = bottomLeft
        indices[pointer++] = topRight
        indices[pointer++] = topRight
        indices[pointer++] = bottomLeft
        indices[pointer++] = bottomRight
      }
    }

    this.mesh = Mesh.construct(gl, vertices, indices, textureCoords, normals)
  }

  setMaterial (mat) {
    this.mesh.material = mat
  }

  draw (gl, shader) {
    super.draw(gl, shader)
    if (!this.mesh) return
    // Set model transform matrix uniform
    const transformLocation = shader.getUniformLocation(gl, 'uModelMatrix')
    gl.uniformMatrix4fv(transformLocation, false, this.transform)

    this.mesh.prepare(gl, shader)
    this.mesh.draw(gl, shader)
    this.mesh.postdraw(gl, shader)
  }
}

export { Terrain }
