<template>
  <div id="player">
    <div id="player-canvas-container">
      <canvas ref="canvas" id="player-canvas" :height="height" :width="width"></canvas>
    </div>
    <div>
      <label for="posSlider">POS</label>
      <input type="range" min="0" :max="frames - 1" value="0" class="slider" id="posSlider" v-model="position">
    </div>
    <button @click="playPause">{{buttonLabel}}</button>
  </div>
</template>

<script>
  export default {
    name: 'player',
    props: {
      width: String,
      height: String
    },
    data: function () {
      return {
        image: null,
        buttonLabel: 'PLAY',
        playing: false,
        position: 0,
        tmp_ctx: null,
        animation_id: null
      }
    },
    computed: {
      frames: function () {
        if (this.image === null) return 0
        return Math.ceil(this.image.width / this.width) *
          Math.ceil(this.image.height / this.height)
      }
    },
    mounted: function () {
      this.$bus.$on('imageLoaded', (image) => {
        this.image = image
      })
      this.clear('red')
    },
    watch: {
      width: function () {
        setTimeout(() => {
          this.clear('red')
        }, 0)
      },
      height: function () {
        setTimeout(() => {
          this.clear('red')
        }, 0)
      },
      position: function () {
        if (this.image === null) return
        this.tmp_ctx = this.$refs.canvas.getContext('2d')
        this.$render()
      }
    },
    methods: {
      playPause: function () {
        this.playing = !this.playing
        if (this.playing) {
          this.tmp_ctx = this.$refs.canvas.getContext('2d')
          this.animation_id = requestAnimationFrame(this.$render_advance)
          this.buttonLabel = 'STOP'
        } else {
          cancelAnimationFrame(this.animation_id)
          this.buttonLabel = 'PLAY'
        }
      },
      clear: function (style) {
        let ctx = this.$refs.canvas.getContext('2d')
        ctx.fillStyle = style
        ctx.fillRect(0, 0, parseInt(this.width), parseInt(this.height))
      },
      $render: function () {
        let wb = Math.ceil(this.image.width / this.width)
        let x = (this.position % wb) * this.width
        let w = x + this.width < this.image.width ? this.width : this.image.width - x
        let y = Math.floor(this.position / wb) * this.height
        let h = y + this.height < this.image.height ? this.height : this.image.height - y
        if (w !== this.width || h !== this.height) this.clear('black')
        this.tmp_ctx.drawImage(this.image, x, y, w, h, 0, 0, w, h)
      },
      $render_advance: function () {
        this.$render()
        if (this.position < this.frames) {
          this.position += 1
          requestAnimationFrame(this.$render_advance)
        }
      }
    }
  }
</script>

<style scoped>

</style>
