
const ENV_MAX_LIGHTS = 4

class Light {
  constructor (pos, color, attenuation = [1.0, 0.0, 0.0]) {
    this.pos = pos
    this.color = color
    this.attenuation = attenuation
  }

  setPosition (pos) {
    this.pos = pos
  }

  setColor (col) {
    this.color = col
  }

  setAttenuation (attn) {
    this.attenuation = attn
  }
}

class SpotLight extends Light {
  constructor (pos, dir, color, attenuation) {
    super(pos, color, attenuation)
    this.dir = dir
  }
}

class DirectionalLight extends SpotLight {
  constructor (pos, dir, color) {
    super(pos, dir, color, [1.0, 0.0, 0.0])
  }
}

class Environment {
  constructor (ambient) {
    this.ambient = ambient

    this.fogStart = 0
    this.fogEnd = 0
    this.fogColor = [0.8, 0.8, 0.8]

    this.sun = new DirectionalLight([0.0, 1000.0, -2000.0], [-1.0, -1.0, 0.0], [1.0, 1.0, 1.0])
    this.lights = [ this.sun ]

    this.maxEnvironmentLights = ENV_MAX_LIGHTS
  }

  addLight (l) {
    if (!(l instanceof Light)) return
    this.lights.push(l)
  }

  addSpotLight (pos, dir, color, attenuation) {
    this.lights.push(new SpotLight(pos, dir, color, attenuation))
  }

  addPointLight (pos, color, attenuation) {
    this.lights.push(new Light(pos, color, attenuation))
  }

  setSunlight (pos, dir, color, attenuation) {
    this.sun = new DirectionalLight(pos, dir, color, attenuation)
    this.lights[0] = this.sun
  }

  setAmbient (color) {
    this.ambient = color
  }

  setFog (color, start, end) {
    this.fogColor = color
    this.fogStart = start
    this.fogEnd = end
  }

  setMaxLights (num) {
    this.maxEnvironmentLights = num
  }

  draw (gl, shader) {
    for (let i = 0; i < this.maxEnvironmentLights; i++) {
      let lightColor = shader.getUniformLocation(gl, 'lightColor[' + i + ']')
      let lightPosition = shader.getUniformLocation(gl, 'lightPosition[' + i + ']')
      let lightAttn = shader.getUniformLocation(gl, 'attenuation[' + i + ']')

      if (this.lights[i]) {
        gl.uniform3fv(lightColor, this.lights[i].color)
        gl.uniform3fv(lightPosition, this.lights[i].pos)
        gl.uniform3fv(lightAttn, this.lights[i].attenuation)
      } else {
        gl.uniform3fv(lightColor, [0.0, 0.0, 0.0])
        gl.uniform3fv(lightPosition, [0.0, 0.0, 0.0])
        gl.uniform3fv(lightAttn, [1.0, 0.0, 0.0])
      }
    }
  }
}

export { Environment, Light, SpotLight, DirectionalLight }
