import Player from "./player.js"
import { Bullet, Meteor, Turret } from "./gameObjects.js"
import { Renderer } from "./renderer.js"
import { setFastTurret, setHeavyTurret, setLaserTurret, setStandardTurret } from "./turretTypes.js"
import { SoundEffect } from "./soundEffect.js"

export default class Game {

  constructor() {
    this.canvas = document.getElementById("mainCanvas")
    this.renderer = new Renderer(this.canvas)
    this.player = new Player()
    this.currentLevel;
    this.nextTurretToFire = 0
    this.turretFire = false
    this.health = 10
    this.healthDisplay = document.getElementById("health")
    this.showTitle = false
    this.lastSlowUpdate = 0
    
    this.ammoCurrent = ""
    this.ammo = {
      laser: 100,
      fast: 100,
      standard: 100,
      heavy: 100
    }

    SoundEffect.setVolumeAll(0.15)

    document.addEventListener("keydown", (event) => {
      switch(event.key) {
        case "p": this.renderer.showStats = !this.renderer.showStats; break
        case "o": this.renderer.showCollisionBox = !this.renderer.showCollisionBox; break
        case "a": this.setTurretTypeAll("laser"); break
        case "z": this.setTurretTypeAll("fast"); break
        case "e": this.setTurretTypeAll("standard"); break
        case "r": this.setTurretTypeAll("heavy"); break
      }
    })
  }

  setGameCanvas(gameCanvas = true) {
    let backgroundColor
    if (gameCanvas) {
      this.canvas = document.getElementById("gameCanvas")
      backgroundColor = "#a9cdd2"
    } else {
      this.canvas = document.getElementById("mainCanvas")
      backgroundColor = "#153a3a"
    }
    this.renderer = new Renderer(this.canvas, backgroundColor)
    this.setSize()
  }

  async loadMainMenu(level) {
    await level.loadLevel()
    this.player.setMusic(level.musicPath)
    this.player.start()
    this.currentLevel = level
  }

  async loadLevel(level) {
    console.log('Set current level:', level.title)

    this.player.stop()

    await level.loadLevel()
    await this.setupTurrets()

    this.showTitle = true
    const mainGameTitle = document.getElementById("main-game-title")
    mainGameTitle.querySelector("h1").innerText = level.title
    mainGameTitle.querySelector("h2").innerText = level.subtitle
    this.setShowTitle(true)
    setTimeout(() => this.setShowTitle(false), 10000)

    this.player.setMusic(level.musicPath)
    this.player.start()

    this.canvas.addEventListener("mousemove", (event) => this.setTurretTarget(event))
    this.canvas.addEventListener("mousedown", () => this.setTurretFire(true))
    this.canvas.addEventListener("mouseup", () => this.setTurretFire(false))
    this.canvas.addEventListener("dblclick", () => this.setTurretFire(!this.turretFire))

    this.setGameOver()
    this.player.audio.addEventListener('ended', () => {
      this.setGameOver(true)
      this.health = 0
    })
    this.currentLevel = level
    this.renderer.bossImg = this.currentLevel.bossImg

    this.ammoCurrent = "standard"
    this.ammo = {
      laser: 100,
      fast: 100,
      standard: 100,
      heavy: 100
    }

    this.setAmmoCounter()
  }

  setShowTitle(show = false) {
    document.getElementById("main-game-title").style.display = show ? "flex" : "none"
  }

  setGameOver(win = false) {
    const gameOverTitle = document.getElementById("game-over")
    gameOverTitle.querySelector("h2").innerText = win ? "YOU HAVE OVERCOME THE ATTACK" : "YOU HAVE PERISHED"
    gameOverTitle.querySelector("h3").innerText = win ? "Until next time" : "Not much to do left"
    gameOverTitle.querySelector("button").innerText = win ? "yay" : "damn"
  }

  setSize(height, width) {
    this.canvas.width = width ?? window.innerWidth
    this.canvas.height = height ?? window.innerHeight
  }

  async setupTurrets() {
    const turretY = this.canvas.height - 155
    const firstTurretX = (this.canvas.width - 1500) / 2 + 95

    this.renderer.turrets.push(new Turret(firstTurretX, turretY))
    this.renderer.turrets.push(new Turret(firstTurretX + 380, turretY - 15))
    this.renderer.turrets.push(new Turret(firstTurretX + 835, turretY - 10))
    this.renderer.turrets.push(new Turret(firstTurretX + 1265, turretY + 5))

    for (const turret of this.renderer.turrets) {
      await setStandardTurret(turret)
    }

    this.ammoCurrent = "standard"
  }

  setTurretTypeAll(type) {
    this.ammoCurrent = type
    this.renderer.turrets.forEach((_, i) => this.setTurretType(i, type))
  }

  async setTurretType(i, type) {
    const turret = this.renderer.turrets[i]

    switch(type) {
      case "standard": await setStandardTurret(turret); break
      case "fast": await setFastTurret(turret); break
      case "laser": await setLaserTurret(turret); break
      case "heavy": await setHeavyTurret(turret); break
    }
  }

  setTurretTarget(event) {
    this.renderer.mouseX = event.offsetX
    this.renderer.mouseY = event.offsetY

    for (const turret of this.renderer.turrets) {
      const dx = this.renderer.mouseX - turret.x
      const dy = this.renderer.mouseY - turret.y
      turret.angle = Math.atan2(dy, dx)
    }
  }

  setTurretFire(fire) {
    this.turretFire = fire
    this.renderer.turrets.forEach((turret) => turret.animationRunning = fire)
  }

  setAmmoCounter() {
    const ammoLaserCounter = document.getElementById("ammo-laser")
    ammoLaserCounter.querySelector("h3").innerText = this.ammo.laser

    const ammoFastCounter = document.getElementById("ammo-fast")
    ammoFastCounter.querySelector("h3").innerText = this.ammo.fast

    const ammoStandardCounter = document.getElementById("ammo-standard")
    ammoStandardCounter.querySelector("h3").innerText = this.ammo.standard

    const ammoHeavyCounter = document.getElementById("ammo-heavy")
    ammoHeavyCounter.querySelector("h3").innerText = this.ammo.heavy
  }

  spawnBullet() {
    if (this.ammo[this.ammoCurrent] <= 0) {
      return
    }

    const turret = this.renderer.turrets[this.nextTurretToFire]
    const deltaLastShot = performance.now() - turret.lastShot
    if (deltaLastShot > turret.firingRate) {
      const angle = turret.angle - ((Math.floor(Math.random() * turret.spread) / 1000) * (Math.random() < 0.5 ? -1 : 1))
      this.renderer.bullets.push(new Bullet(turret.x , turret.y, angle, turret.bulletSprite, turret.damage, turret.aoe, turret.aoeSize, turret.percing, turret.bulletHealth))
      turret.lastShot = performance.now()
    }

    this.nextTurretToFire = this.nextTurretToFire < this.renderer.turrets.length - 1 ? this.nextTurretToFire + 1 : 0
  }

  spawnMeteor() {
    this.renderer.meteors.push(new Meteor(this.canvas.width, this.canvas.height, this.currentLevel.maxHealth, this.currentLevel.meteorImg, this.currentLevel.meteorImgList))
  }

  render() {
    // Frames
    const now = performance.now()
    if ((now - this.renderer.lastFrame) > (1000 / 60)) {
      if (this.turretFire) {
        this.spawnBullet()
      }

      const damageTaken = this.renderer.render()

      if (damageTaken > 0 && this.currentLevel.title !== "MainMenu") {
        SoundEffect.explosionBig.play()
        this.health -= damageTaken
      }

      this.healthDisplay.innerText = `${this.health} HP`
    }

    // Slow updates
    if ((now - this.lastSlowUpdate) > 1000) {
      if (this.turretFire) {
        this.ammo.laser = this.ammo.laser + 1 < 100 ? this.ammo.laser + 1 : 100
        this.ammo.fast = this.ammo.fast + 5 < 100 ? this.ammo.fast + 5 : 100
        this.ammo.standard = this.ammo.standard + 2 < 100 ? this.ammo.standard + 5 : 100
        this.ammo.heavy = this.ammo.heavy + 0.5 < 100 ? this.ammo.heavy + 2 : 100

        this.ammo[this.ammoCurrent] = this.ammo[this.ammoCurrent] - 5 > 0 ? this.ammo[this.ammoCurrent] - 5 : 0

        this.setAmmoCounter()
      }
      
      this.lastSlowUpdate = now
    }
  }

}