<template>
  <div class="box">
    <div id="menu">
      <span class="submenu">
        <span>{{ status }}</span>&nbsp; SOCKET
      </span>
      <span class="submenu">
        <span>
          <span
            v-for="(item, index) in colors"
            :key="index"
            @click="restColor(index)"
          >{{ item }}</span>
        </span>
        <span>
          <a
            href="https://beian.miit.gov.cn/"
            target="_blank"
            rel="noopener noreferrer"
          >蜀ICP备2021004869号-1</a>
        </span>
      </span>
    </div>
    <div id="cursors" />
    <canvas
      id="canvas"
      :style="resetStyle"
    />
  </div>
</template>
<script lang="ts" setup>
import { Painter } from './js/Painter.js'
import { Recorder } from './js/Recorder.js'
import {
  onMounted, ref, nextTick, onUnmounted
} from 'vue'
import { io } from 'socket.io-client'

const painters: any = {}
let recorder: any = null
let ptime = 0
const status = ref('🟡')
const colors = [ '⚫️', '🔵', '🟢', '🟣', '🔴', '🟤', '🟠', '🟡', '⚪️' ]
let canvas: HTMLCanvasElement | null = null
let context: CanvasRenderingContext2D | null = null
const resetStyle = ref('')

// canvas fn
const onPointerMove = (event: PointerEvent) => {
  if (event.isPrimary) {
    // Throttle to 20Hz
    const throttle = 1000 / 20
    const time = event.timeStamp
    if (time < (ptime + throttle)) return
    ptime = time
    //
    const x = Math.floor(event.pageX * window.devicePixelRatio)
    const y = Math.floor(event.pageY * window.devicePixelRatio)
    recorder.move(x, y)
  }
}

const onPointerDown = (e: PointerEvent) => {
  if (e.isPrimary && e.button === 0 && canvas) {
    const x = Math.floor(e.pageX * window.devicePixelRatio)
    const y = Math.floor(e.pageY * window.devicePixelRatio)
    recorder.down(x, y)
    canvas.addEventListener('pointermove', onPointerMove)
  }
}

const onPointerUp = (event: PointerEvent) => {
  if (event.isPrimary && event.button === 0) {
    recorder.up()
    canvas?.removeEventListener('pointermove', onPointerMove)
  }
}

const restColor = (i: number) => {
  recorder.color(i)
  const w = canvas?.width || 0
  const h = canvas?.height || 0
  const r = window.devicePixelRatio
  resetStyle.value = `width:${w / r}px;height:${h / r}px; cursor: url(/pen/${i}.cur) 0 17, crosshair;`
}

// socket init
const socket = io(import.meta.env.VITE_SOCKET_URL, { autoConnect: false, auth: { roomID: 'drawCanvas', name: 'test' }, transports: [ 'websocket' ] })
socket.on('connect', () => {
  recorder = new Recorder(context, socket)
  canvas?.addEventListener('pointerdown', onPointerDown)
  canvas?.addEventListener('pointerup', onPointerUp)
  status.value = colors[2]
})

socket.on('msg', (data: any) => {
  const dataview = new DataView(data)
  const id = dataview.getUint8(0)
  if (painters[id] === undefined) {
    const container = document.getElementById('cursors')
    painters[id] = new Painter(context, container)
  }
  painters[id].execute(dataview)
})

socket.on('connect_error', () => {
  status.value = colors[4]
})

//  init canvas
const intCanvas = () => {
  canvas = document.getElementById('canvas') as HTMLCanvasElement
  canvas.width = window.innerWidth * window.devicePixelRatio
  canvas.height = window.innerHeight * window.devicePixelRatio
  canvas.style.width = `${window.innerWidth}px`
  canvas.style.height = `${window.innerHeight}px`
  context = canvas.getContext('2d') as CanvasRenderingContext2D
  context.lineWidth = 0.7 * window.devicePixelRatio
  context.fillStyle = 'rgb(238, 238, 238)'
  context.fillRect(0, 0, canvas.width, canvas.height)
}

onMounted(() => {
  document.title = '多人在线画板'
  intCanvas()
  nextTick(() => {
    socket.connect()
  })
  window.addEventListener('resize', intCanvas)
})

onUnmounted(() => {
  if (!socket) return
  socket.disconnect()
  window.removeEventListener('resize', intCanvas)
  context = null
  canvas = null
  recorder = null
})
</script>
<style lang="scss" scoped>
.box {
  background: #eeeeee;
  font-size: 12px;
  font-family: sans-serif;
  margin: 0;
  overflow: hidden;

  #canvas {
    display: block;
    cursor: url('/pen/0.cur') 0 17, crosshair;
    touch-action: none;
  }

  #cursors {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    pointer-events: none;
  }

  #menu {
    position: absolute;
    bottom: 10px;
    width: 100%;
    text-align: center;
    user-select: none;
    pointer-events: none;
  }

  span.submenu {
    display: inline-block;
    background-color: #ffffff;
    color: #999999;
    padding: 6px 12px;
    border-radius: 25px;
    user-select: none;
    pointer-events: auto;

    &:last-child {
      margin-left: 5px;
    }

    &>span {
      span {
        margin: 0 3px;
        cursor: grabbing;
      }
    }
  }

}
</style>