<script setup lang="ts">
import GameComponent from '@/components/GameComponent.vue'
import TileComponent from '@/components/TileComponent.vue'
import type { GameState, PlayerState } from '@/utilities/interfaces'
import { inject, onBeforeUnmount, ref } from 'vue'
import { onMounted } from 'vue'

const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

const socketService: any = inject('socket')
const { socket } = socketService
let gameState = ref<GameState | undefined>(undefined)
let playerState = ref<PlayerState | undefined>(undefined)
let data = ref('')
let responseField = ref('')
let statusField = ref('')
let sessionId = ref('')
let selectdAction: any = undefined
let canSelectTile = false
let canMakeMove = false
let tileSelected = ''
let moveType = ''

const options = [
  { value: 'createSession', default: '{"user": "arhuako"}' },
  { value: 'startSession', default: (id: string) => `{"sessionId": "${id}"}` },
  { value: 'joinSession', default: '{"user": "pepe", "sessionId": "arhuako"}' },
  { value: 'leaveSession', default: '{"user": "pepe", "sessionId": "arhuako"}' },
  { value: 'chat message', default: 'chat message' }
]

onMounted(async () => {
  socket.on('gameState', (data: GameState, callback: any) => {
    gameState.value = data
    statusField.value = statusField.value + JSON.stringify(data, null, 2)
    callback({
      status: 'ok'
    })
  })

  socket.on('playerState', (data: PlayerState, callback: any) => {
    console.log('playerState :>> ', data)
    playerState.value = data
    statusField.value = statusField.value + JSON.stringify(data, null, 2)
    callback({
      status: 'ok'
    })
  })

  socket.on('makeMove', async (data: any, callback: any) => {
    statusField.value = statusField.value + JSON.stringify(data, null, 2)
    canMakeMove = true
    while (canMakeMove) {
      await wait(500)
    }
    callback({
      status: 'ok',
      tileId: tileSelected,
      moveType
    })
  })

  socket.on('chooseTile', async (data: any, callback: any) => {
    statusField.value = statusField.value + JSON.stringify(data, null, 2)
    canSelectTile = true
    while (canSelectTile) {
      await wait(500)
    }
    callback({
      status: 'ok',
      tileId: tileSelected
    })
  })
})

function selectTile(id: string) {
  if (canSelectTile) {
    tileSelected = id
    canSelectTile = false
  }
}

function selectTileToMove(id: string) {
  if (canMakeMove) {
    if (tileSelected === id) {
      tileSelected = ''
      return
    }
    tileSelected = id
  }
}

function onTileClick(tileId: string) {
  console.log('tileId :>> ', tileId)
  selectTile(tileId)
}

function makeMove(type: string) {
  if (canMakeMove) {
    if (type === 'pass') {
      tileSelected = ''
      canMakeMove = false
    } else if (tileSelected) {
      moveType = type
      canMakeMove = false
    }
  }
}

onBeforeUnmount(() => {
  socketService.disconnect()
})

function actionSelected() {
  console.log('event :>> ', selectdAction)

  if (selectdAction.value === 'createSession') {
    responseField.value = ''
  } else if (selectdAction.value === 'startSession') {
    data.value = selectdAction.default(sessionId.value)
    return
  }

  data.value = selectdAction.default
}

const getMessage = (msg: string) => {
  if (msg.startsWith('{') && msg.endsWith('}')) return JSON.parse(msg)
  return msg
}

async function sendMessage() {
  if (selectdAction && data.value.trim() !== '') {
    console.log('socketService :>> ', socketService)

    const response = await socketService.sendMessageWithAck(
      selectdAction.value,
      getMessage(data.value.trim())
    )
    console.log('response :>> ', response)
    handleResponse(response)
  }
  // socketService.emit('message', data.value)
}

function handleResponse(response: any) {
  if (selectdAction.value === 'createSession') {
    sessionId.value = response.sessionId
  }

  data.value = ''
  const responseStr = JSON.stringify(response, null, 2)
  responseField.value = !responseField.value
    ? responseStr
    : responseField.value + '\n---\n ' + responseStr
  selectdAction = undefined
}
</script>

<template>
  <div class="grid">
    <div>
      <GameComponent :gameState="gameState" :playerState="playerState" @tileClick="onTileClick" />
      <p>SessionID: {{ sessionId }}</p>
      <ul id="messages"></ul>
      <form id="form" action="">
        <p>
          <select v-model="selectdAction" id="event" autocomplete="off" @change="actionSelected">
            <option value="">Select event</option>
            <option :key="option.value" v-for="option in options" :value="option">
              {{ option.value }}
            </option>
          </select>
        </p>
        <!-- <p><input id="room" autocomplete="off" /></p> -->
        <p>
          <textarea v-model="data" id="message" autocomplete="off" placeholder="Data"></textarea>
        </p>
        <p><button @click.prevent.stop="sendMessage">Send</button></p>
        <div class="grid">
          <div>
            <textarea
              :value="responseField"
              id="response"
              autocomplete="off"
              placeholder="Response"
            ></textarea>
          </div>
          <div>
            <textarea
              :value="statusField"
              id="status"
              autocomplete="off"
              placeholder="Game status"
            ></textarea>
          </div>
        </div>
      </form>
    </div>
    <div>
      <!-- <div style="display: flex; gap: 4px">
        <TileComponent :revealed="false" :top="6" :bottom="0" />
        <TileComponent :revealed="true" :top="6" :bottom="0" />
      </div> -->
      <h4>Board</h4>
      <!-- Board -->
      <div class="board-container">
        <div v-if="gameState?.tileSelectionPhase">
          <div class="tiles-container">
            <TileComponent
              :key="tile.id"
              v-for="tile in gameState.boneyard"
              @tile-clicked="selectTile(tile.id)"
            />
          </div>
          <div v-if="canSelectTile">Please select a tile.</div>
          <div v-else>Wait your turn.</div>
        </div>
        <div v-if="!gameState?.tileSelectionPhase">
          <div class="tiles-container">
            <TileComponent
              :class="{ 'selected-tile': tileSelected === tile.id }"
              :revealed="true"
              :key="tile.id"
              v-for="tile in gameState?.board"
              :top="tile.pips[0]"
              :bottom="tile.pips[1]"
            />
          </div>
        </div>
      </div>
      <!-- End board-->

      <div class="hand-container">
        <h4>
          Your Hand <button class="control" @click="makeMove('left')">Left</button
          ><button class="control" @click="makeMove('right')">Right</button
          ><button class="control" @click="makeMove('pass')">Pass</button>
        </h4>
        <div class="tiles-container">
          <TileComponent
            :revealed="true"
            :key="tile.id"
            v-for="tile in playerState?.hand ?? []"
            @tile-clicked="selectTileToMove(tile.id)"
            :top="tile.pips[0]"
            :bottom="tile.pips[1]"
          />
        </div>
      </div>
      <!-- End hand-->
    </div>
  </div>
</template>

<style scoped lang="scss">
* {
  box-sizing: border-box;
}

.control {
  font-size: 60%;
  padding: 8px;
  margin-right: 4px;
}

textarea {
  width: 100%;
  height: 150px;
  resize: none;
  font-size: 70%;
}
#response,
#status {
  height: 400px;
}

.tiles-container {
  display: flex;
  gap: 4px;
  flex-flow: row wrap;
  align-content: flex-start;
}

.board-container {
  position: absolute;
  height: 600px;
  padding: 10px;
  width: calc(50% - 50px);
  background-color: var(--pico-form-element-background-color);
}

.hand-container {
  position: fixed;
  bottom: 0;
  height: 200px;
  padding: 10px;
  width: calc(50% - 50px);
  background-color: var(--pico-form-element-background-color);
}
</style>
