<template>
  <main id="main">
    <canvas
      id="canvas"
      ref="canvas"
      :width="canvasWidth"
      :height="canvasHeight"
    />
  </main>
</template>
<script>
import { create1dState, create1dStateOneCell, create2dState, createBoard, conwayRules, evolve2d } from '../modules/automata.js'
import { getRandomInt, sleep } from '../modules/common.js'
import {mapGetters} from 'vuex'
export default {
  name: 'Canvas',
  data() {
    return {
      canvas: null,
      ctx: null,
    }
  },
  computed: {
    ...mapGetters({
      cellProperties: 'getCellProperties',
      rules: 'get1dRules',
      drawing: 'isDrawing',
      canvasWidth: 'getCanvasWidth',
      canvasHeight: 'getCanvasHeight',
      refreshRate: 'getRefreshRate',
      initial1dState: 'getInitial1dState'
    }),
    boardWidth: function() {
      return Math.floor(
        this.canvas.width /
          this.cellProperties.size)
    },
    boardHeight: function() {
      return Math.floor(
        this.canvas.height /
          this.cellProperties.size)
    }
  },
  mounted() {
    this.canvas = this.$refs['canvas']
    this.ctx = this.canvas.getContext('2d')
    this.$root.$on('draw1d', () => { this.draw1d() })
    this.$root.$on('draw2d', () => { this.draw2d() })
    this.$root.$on('reset', () => { this.reset() })
    this.$root.$on('stop', () => { this.stop() })
  },
  methods: {
    drawCanvas(board) {
      const props = this.cellProperties
      board.map((row, y) => {
        const d = props.size
        return row.map(
          (cell, x) => {
            this.ctx.fillStyle = (
              () => {
                if (cell === 1) return props.liveColor
                return props.deadColor
              })()
            this.ctx.fillRect(x * d, y * d, d, d)
            return cell
          },
        )
      })
    },
    compute1dInitialState() {
      if(this.initial1dState === "onecell")
        return create1dStateOneCell(this.boardWidth)
      return create1dState(this.boardWidth, getRandomInt, [0, 2])
    },
    async draw1d() {
      const initialState = this.compute1dInitialState()
      const board = createBoard(
        initialState,
        this.rules,
        this.boardHeight
      )
      this.drawCanvas(board)
    },
    async draw2d() {
      if (this.drawing === 0) return
      const initialState = create2dState(
        this.boardWidth,
        this.boardHeight,
        getRandomInt,
        [0, 2],
      );
      const board = evolve2d(initialState, conwayRules);
      
      const draw2dNext = async (b) => {
        if (this.drawing === 0) return
        const newBoard = evolve2d(b, conwayRules)
        this.drawCanvas(b, this.cellProperties)
        await sleep(this.refreshRate)
        draw2dNext(newBoard)
      }
      return draw2dNext(board)
    },
    stop() {
      this.$store.commit('setDrawingStatus', 0)
    },
    reset() {
      this.stop()
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
    }
  }
}
</script>

