<template>
  <div class="game">
    <b-modal v-model="playerIsDead">
      <h1 class="titleDed">DED</h1>
      <h2 class="title">Score: {{player.score}}</h2>
      <h3 class="subtitle">Best score: {{player.bestScore}}</h3>
      <b-button @click="respawn">Respawn</b-button>
      <b-button @click="quit">Quit</b-button>
    </b-modal>
    <canvas
      class="game-canvas"
      ref="canvas">
    </canvas>
  </div>
</template>

<script>
import { send } from '@/store/socketPlugin'
import { render } from '@/game/render.js'
import { sound } from '@/game/sound.js'
import { Explosion } from '@/game/sprites.js'

export default {
  name: 'Game',
  props: ['showDebug', 'showLeaderboard'],
  data () {
    return {
      mouse: {
        x: 0,
        y: 0
      },
      camera: {
        x: 0,
        y: 0
      },
      stats: {
        totalWalls: 0,
        lastUpdateTime: {},
        lastFrame: 0,
        lastSpriteFrame: 0
      },
      deadPlayers: [],
      renderTimer: null
    }
  },
  computed: {
    canvas () {
      return this.$refs.canvas
    },
    context () {
      return this.canvas.getContext('2d')
    },
    settings () {
      return this.$store.state.game.settings
    },
    player () {
      return this.$store.state.game.player
    },
    sprites () {
      return this.$store.state.game.sprites
    },
    players () {
      const pastUpdate = this.$store.state.game.updates[0]
      const nextUpdate = this.$store.state.game.updates[1]

      if (pastUpdate === undefined) return []
      if (pastUpdate.players === undefined) return []
      if (nextUpdate === undefined) return pastUpdate.players

      return nextUpdate.players
    },
    isPaused () {
      return this.$store.state.game.paused
    },
    leaderboard () {
      return this.$store.state.game.leaderboard
    },
    playerIsDead () {
      return this.player.state === 'DEAD'
    }
  },
  mounted () {
    this.setCanvasSize()
    this.canvas.addEventListener('mousemove', this.mouseEvent)
    this.canvas.addEventListener('touchmove', this.touchEvent)
    this.canvas.addEventListener('resize', this.setCanvasSize)
    // this.renderTimer = setInterval(this.render, 1000 / 60)
    // this.renderTimer = setInterval(this.renderSprites, 1000 / 30)
    this.render()
  },
  methods: {
    render () {
      this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
      render.borders(this.context, this.canvas, this.camera, this.settings)

      // const players = update.computePlayers(this.$store.state.game.updates, this.$store.state.game.firstUpdateTime, this.$store.state.game.gameStartTime)

      if (!this.players) return
      this.stats.totalWalls = 0

      this.players.forEach(player => {
        if (player.color === this.player.color) {
          this.camera.x = player.x
          this.camera.y = player.y
        }

        if (player.state === 'DEAD') this.context.globalAlpha = 0.1

        // render.wallsBezier(this.context, this.canvas, this.camera, this.settings, player)
        render.walls(this.context, this.canvas, this.camera, this.settings, player)

        if (player.name === 'e' || player.name === 'q' || player.name === 'r' || player.name === 't') render.playerFace(this.context, this.canvas, this.camera, this.settings, player, player.name)
        else render.player(this.context, this.canvas, this.camera, this.settings, player)

        if (player.state === 'DEAD') this.context.globalAlpha = 1

        this.stats.totalWalls += player.walls.length

        // Check if player was dead before for one time event
        if (player.state === 'DEAD' && !this.deadPlayers.includes(player.id)) {
          this.deadPlayers.push(player.id)
          sound.explosion()
          this.sprites.push(new Explosion(player.x, player.y))
        }

        // Remove player from dead list
        if (player.state !== 'DEAD' && this.deadPlayers.includes(player.id)) {
          const i = this.deadPlayers.indexOf(player.id)
          this.deadPlayers.splice(i, 1)
        }
      })

      this.renderSprites()

      render.mouse(this.context, this.mouse, this.player)

      if (this.showLeaderboard) {
        render.leaderboard(this.context, this.canvas, this.leaderboard)
      }

      if (this.showDebug) {
        render.debug(this.context, this.camera, this.mouse, this.canvas, this.stats)
      }

      this.stats.lastFrame = performance.now()

      const nextUpdate = this.$store.state.game.updates[1]
      if (nextUpdate !== undefined) this.stats.lastUpdateTime = nextUpdate.time
      requestAnimationFrame(this.render, this.canvas)
    },
    renderSprites () {
      let nextFrame = false
      // Check if needed to show next frame for animations
      if ((performance.now() - this.stats.lastSpriteFrame) > 50) {
        nextFrame = true
        this.stats.lastSpriteFrame = performance.now()
      }

      this.sprites.forEach((sprite, index, object) => {
        render.sprite(this.context, this.canvas, this.camera, sprite)
        if (nextFrame) {
          if (sprite.framesCounter === sprite.frames) {
            if (sprite.removeAfterAnimation) {
              object.splice(index, 1)
            } else {
              // console.log('SPRITE ', index, 'frame reset')
              sprite.framesCounter = 0
            }
          } else {
            // console.log('SPRITE ', index, 'frame++', sprite.framesCounter)
            sprite.framesCounter++
          }
        }
      })
    },
    mouseEvent (event) {
      var rect = this.canvas.getBoundingClientRect()
      this.mouse.x = event.clientX - rect.left
      this.mouse.y = event.clientY - rect.top

      this.sendAngleUpdate()
    },
    touchEvent (event) {
      var rect = this.canvas.getBoundingClientRect()
      this.mouse.x = event.touch[0].clientX - rect.left
      this.mouse.y = event.touch[0].clientY - rect.top

      this.sendAngleUpdate()
    },
    sendAngleUpdate () {
      var dx = this.mouse.x - this.canvas.width / 2
      var dy = this.mouse.y - this.canvas.height / 2

      this.player.targetAngle = Math.atan2(dy, dx)
      this.player.angle = this.player.targetAngle
      send({ player: this.player, type: 'update' })
    },
    updatePlayer (player) {
      player.x += this.settings.playerSpeed * Math.cos(player.angle)
      player.y += this.settings.playerSpeed * Math.sin(player.angle)

      player.angle = player.targetAngle
    },
    interpolatePlayer (pastPlayer, nextPlayer, dt) {
      var player = {}
      player.color = pastPlayer.color
      player.walls = pastPlayer.walls
      player.lastWall = pastPlayer.lastWall

      player.x = pastPlayer.x + (nextPlayer.x - pastPlayer.x) * dt
      player.y = pastPlayer.y + (nextPlayer.y - pastPlayer.y) * dt

      player.angle = pastPlayer.angle + (nextPlayer.angle - pastPlayer.angle) * dt
      player.targetAngle = pastPlayer.targetAngle + (nextPlayer.targetAngle - pastPlayer.targetAngle) * dt

      return player
    },
    setCanvasSize () {
      this.canvas.width = window.innerWidth
      this.canvas.height = window.innerHeight
    },
    respawn () {
      send({ type: 'respawn' })
    },
    quit () {
      send({ type: 'logout' })
      this.$store.dispatch('game/logout')
    }
  }
}
</script>

<style>
.titleDed {
  display: inline-block;
  font-family: TRON;
  font-size: 70px;
  color: #cf0cb4ff;
  margin-bottom: 25px;
}
</style>
