<template>
  <AppHeader />

  <!-- Number to find -->
  <PlaquetteBox
    class="p-1 mx-auto mb-4 w-fit"
    :class="{
      'text-blue-400': difficultyLevel === 1,
      'text-purple-500': difficultyLevel === 2,
    }">
    <span class="text-4xl">{{ result }}</span>
  </PlaquetteBox>

  <!-- Start button -->
  <!-- TODO: fix animation -->
  <Transition name="zero_height">
    <div
      class="text-center"
      v-if="gameState === GameState.Waiting">
      <div>
        Combinez les nombres imposés afin de trouver le résultat ci-dessus, ou
        de vous en approcher le plus possible.<br>
        Le compteur démarre quand vous cliquez sur le bouton.<br>Partagez vos
        meilleurs temps !
      </div>

      <button
        @click="startGame"
        class="py-2 px-4 mt-4 btn">
        {{ t('startGame') }}
      </button>
    </div>
  </Transition>

  <!-- PLAQUETTES -->
  <PlaquettesList
    :plaquettes="shownPlaquettes"
    @click-number="selectNumber" />

  <Transition name="slide_up">
    <div v-if="gameIsRunning">
      <!-- OPERATORS -->
      <OperatorsList @click="selectOperator" />

      <!-- Divider -->
      <div class="my-4 mx-auto max-w-sm border-b" />

      <!-- List of Operations -->
      <OperationsList v-show="gameIsRunning" />
    </div>
  </Transition>

  <Transition name="slide_up">
    <div
      v-if="isEndGame"
      class="flex flex-row justify-evenly items-center mx-auto mt-8 max-w-sm">
      <span
        v-if="isResultPerfect"
        v-html="t('endGame.victoryLabel')" />
      <span
        v-else
        v-html="t('endGame.failureLabel')" />
      <button
        class="p-2 rounded border"
        @click="reboot">
        {{ t('playAgain') }}
      </button>
    </div>
  </Transition>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute } from 'vue-router'

import {
  getEmptyOperation,
  isOperationReady,
  isOperationResultValid,
  isSolvable,
  operate,
} from '@/algo'
import AppHeader from '@/components/AppHeader.vue'
import PlaquetteBox from '@/components/common/PlaquetteBox.vue'
import OperationsList from '@/components/OperationsList.vue'
import OperatorsList from '@/components/OperatorsList.vue'
import PlaquettesList from '@/components/PlaquettesList.vue'
import {
  currentOperation,
  gameIsRunning,
  gameState,
  isEndGame,
  isResultPerfect,
  operations,
  plaquettes,
  result,
} from '@/composables/game-state'
import { GameState, pools } from '@/globals'
import { OperatorType, Plaquette } from '@/types'
import { randItem, randRange } from '@/utils'

const { t } = useI18n() // call `useI18n`, and spread `t` from  `useI18n` returning

/*
 * Computed & refs
 */

const difficultyLevel = ref<1 | 2>(1)

const isDaily = computed(() => useRoute().name === 'daily')
const shownPlaquettes = computed(() =>
  gameIsRunning.value ? plaquettes.value : [],
)

/*
 * Watchers
 */

watch(
  currentOperation,
  op => {
    if (isOperationReady(op) && isOperationResultValid(op) && !op.result) {
      op.result = {
        free: true,
        value: operate(op.operator!, op.left!.value, op.right!.value),
      }
      if (operations.length < 5 && !isEndGame.value) {
        plaquettes.value.push(op.result)
        operations.push(getEmptyOperation())
      }
    }
  },
  { deep: true },
)

function startGame(): void {
  gameState.value = GameState.Loading
  setTimeout(() => (gameState.value = GameState.Playing), 500)
}

function selectNumber(p: Plaquette): void {
  if (isEndGame.value) return

  const op = currentOperation.value
  if (!p.free) return

  if (!op.left) {
    op.left = p
    p.free = false
  }
  else if (!op.right) {
    op.right = p
    p.free = false
  }
}

/*
 * Functions
 */

function selectOperator(o: OperatorType): void {
  if (isEndGame.value) return
  currentOperation.value.operator = o
}

function reboot(): void {
  gameState.value = GameState.Playing
  do {
    // Find a problem
    // result.value = randRange(101, 1000)
    difficultyLevel.value = randItem([1, 1, 1, 1, 2])
    result.value = (() => {
      switch (difficultyLevel.value) {
        case 1:
          return randRange(101, 1000)
        case 2:
          return randRange(101, 1000)
      }
    })()
    // result.value = 29
    // Reset Operations list
    operations.splice(0)
    operations.push(getEmptyOperation())

    // Generate result and plaquettes
    plaquettes.value = []
    const poolCopy = [...pools[difficultyLevel.value]]
    for (let i = 0; i < 6; ++i) {
      const random = Math.floor(Math.random() * poolCopy.length)
      const el = poolCopy.splice(random, 1)[0]
      plaquettes.value.push({ value: el, free: true })
    }
    // plaquettes.value = [4, 8, 10, 25, 50, 100].map(value => ({
    //   free: true,
    //   value,
    // }))
    // Solve it
  } while (
    !isSolvable(
      result.value,
      plaquettes.value.map(p => p.value),
    )
  )
  plaquettes.value.sort((a, b) => a.value - b.value)
}

/*
 * Hooks
 */

onMounted(() => {
  reboot()
  gameState.value = GameState.Waiting
})

onUnmounted(() => {
  gameState.value = GameState.Waiting
})
</script>
