<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css">
    <script src="//cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  </head>
  <body>
    <h1>Hello Plunker!</h1>
    <div id='app'>
      <p>SCORE: {{ snake.body_indexes.length - 1 }}</p>
      <div id='map'>
        <div v-for="i in grid_size * grid_size" :class="{
          cell: true,
          head: snake_head_index === i - 1,
          body: snake.body_indexes.includes(i - 1),
          fruit: fruit_index === i - 1,
        }">
           {{ i - 1 }} 
        </div>
      </div>
      <p v-if='is_gameover'>
        GAME OVER<br>
        <button onclick="location.reload()">RETRY</button>
      </p>
    </div>
    <script src="script.js"></script>
  </body>
</html>





new Vue({
  el: '#app',
  data: {
    grid_size: 10,
    fruit_index: 0, 
    snake: {
      head_pos: {
        x: 1,
        y: 3,
      },
      body_indexes: [0], 
      direction: '→', 
      speed: 800, 
    },
  },
  created() {
    this.randomize_fruit_index()
    document.onkeydown = () => {
      this.on_keydown(event.keyCode)
    }
    this.time_goes()
  },
  watch: {
    is_eating_fruit(newValue) {
      if (!newValue) 
        return 
      this.grow_up_snake()
      this.randomize_fruit_index()
    },
  },
  computed: {
    snake_head_index() {
      if (this.is_frameout) 
        return null
      return this.snake.head_pos.y * this.grid_size + this.snake.head_pos.x
    },
    is_eating_fruit() {
      return this.snake_head_index === this.fruit_index
    },
    is_suicided() {
      return this.snake.body_indexes.includes(this.snake_head_index)
    },
    is_frameout() {
      const head = this.snake.head_pos
      return head.x < 0 || this.grid_size <= head.x || head.y < 0 || this.grid_size <= head.y
    },
    is_gameover() {
      return this.is_suicided || this.is_frameout
    },
  },
  methods: {
    time_goes() {
      if (this.is_gameover) 
        return
      this.forward_snake()
      setTimeout(this.time_goes.bind(this), this.snake.speed)
    },
    forward_snake() {
      this.snake.body_indexes.shift()
      this.snake.body_indexes.push(this.snake_head_index)
      switch(this.snake.direction) 
      {
      case '←': 
        this.snake.head_pos.x--;
      break
      case '↑':
        this.snake.head_pos.y--;
      break
      case '→': 
        this.snake.head_pos.x++;
      break
      case '↓': 
        this.snake.head_pos.y++;
      break
      }
    },
    grow_up_snake() {
      this.snake.body_indexes.unshift(this.snake.body_indexes[0])
    },
    randomize_fruit_index() {
      this.fruit_index = Math.floor(Math.random() * this.grid_size * this.grid_size) 
    },
    on_keydown(keyCode) {
      switch(keyCode) 
      {
      case 37:  
        if (this.snake.direction !== '→')
        {
          this.snake.direction = '←';
        }
      break
      case 38:   
        if (this.snake.direction !== '↓')
        {
          this.snake.direction = '↑';
        }
      break
      case 39: 
        if (this.snake.direction !== '←')
        {
          this.snake.direction = '→'; 
        }
      break
      case 40: 
        if (this.snake.direction !== '↑')
        {
          this.snake.direction = '↓';
        }
      break
      }
    }
  },
})
        
        
        
/* Styles go here */

 #map {
  --grid-size: 10;
  display: grid;
  grid-template-columns: repeat(var(--grid-size), 30px);
  grid-template-rows: repeat(var(--grid-size), 30px);
}
.cell {
  border: 1px solid white;
  background: pink;
}
.cell.body {
  background: silver;
}
.cell.fruit {
  background: orangered;
}
.cell.head {
  background: dimgray;
}