<template>
  <div class="platine" :class="{ 'loading': isLoadingCard, 'mounted': isMounted }" ref="platine">
    <div class="disc" ref="discRef" id="disc">
      <div class="bobine" :style="{
        height: progressPercentage + '%',
        width: progressPercentage + '%'
      }"></div>
      <div class="power-button" @mousedown.stop @click.stop="handlePowerButtonClick">
        <img class="power-logo" src="/favicon.svg">
        <div class="power-loading" v-if="isLoadingCard">
          <div class="spinner"></div>
        </div>
      </div>
      <div class="turn-point" v-if="!isLoadingCard">
      </div>
    </div>
    <div class="debug">
      <b>progressPercentage</b>: <br>
      </br>{{ Math.round(progressPercentage) }}%
      <br>
      <b>Disc</b>: <br>
      </br>{{ Math.round(disc?.secondsPlayed || 0) }}sec
      <br>
      </br>{{ Math.round(sampler?.duration || 0) }}sec
      <br>
      <!-- <pre>{{ sampler }}</pre> -->
      isPlaying:
      </br>{{ isPlaying }}
      <br>
      <b>isFirstDrag</b>: <br>
      </br>{{ isFirstDrag }}
    </div>
  </div>
</template>

<script setup lang="ts">
import type { Card } from '~~/types/types'
import { ref, onMounted, onUnmounted, watch, computed } from 'vue'
import Disc from '~/utils/platine/disc'
import Sampler from '~/utils/platine/sampler'

const props = defineProps<{ card?: Card }>()

// State
const isLoadingCard = ref(false)
const isFirstDrag = ref(true)
const progressPercentage = ref(0)
const currentTurns = ref(0)
const totalTurns = ref(0)// Refs pour les instances

// Refs pour les instances
const disc = ref<Disc | null>(null)
const sampler = ref<Sampler | null>(null)
const discRef = ref<HTMLElement>()
const platine = ref<HTMLElement>()
const isMounted = ref(false)

const isPlaying = computed(() => Math.abs(Math.round(sampler.value?.currentSpeed || 0)) !== 0)

// Actions
const initPlatine = (element: HTMLElement) => {
  // console.log('[INIT] Platine')
  discRef.value = element
  disc.value = new Disc(element)
  sampler.value = new Sampler()

  // Configurer les callbacks du disque
  if (disc.value) {
    disc.value.callbacks.onStop = () => {
      // console.log('[DISC] On Stop')
      sampler.value?.pause()
    }

    disc.value.callbacks.onDragStart = () => {
      // console.log('[DISC] On Drag Start')
      if (isFirstDrag.value) {
        isFirstDrag.value = false
        // togglePlay()
        if (sampler.value && disc.value) {
          sampler.value.play(disc.value.secondsPlayed)
          disc.value.powerOn()
          // console.log('[DISC] Power ON')
        }
      }
    }

    disc.value.callbacks.onDragEnded = () => {
      // console.log('[DISC] On Drag END')
      sampler.value?.play(disc.value?.secondsPlayed || 0)
    }

    disc.value.callbacks.onLoop = ({ playbackSpeed, isReversed, secondsPlayed }) => {
      // Ne mettre à jour que si nécessaire et s'assurer que la position est valide
      if (Math.abs((sampler.value?.currentSpeed || 0) - playbackSpeed) > 0.01) {
        const safeSecondsPlayed = Math.max(0, secondsPlayed)
        sampler.value?.updateSpeed(playbackSpeed, isReversed, safeSecondsPlayed)
      }
      updateTurns()
    }
  }
}

const updateTurns = () => {
  if (!disc.value) return

  const newTurns = disc.value.secondsPlayed * 0.75
  const newTotalTurns = (disc.value as any)._duration * 0.75

  // Calcul du pourcentage de progression pour l'affichage visuel (22% à 100%)
  const minPercentage = 22
  const progressRatio = disc.value.secondsPlayed / (disc.value as any)._duration
  const newProgressPercentage = minPercentage + (progressRatio * (100 - minPercentage))

  // Ne mettre à jour que si les valeurs ont changé de manière significative
  if (
    Math.abs(currentTurns.value - newTurns) > 0.01 ||
    Math.abs(totalTurns.value - newTotalTurns) > 0.01 ||
    Math.abs(progressPercentage.value - newProgressPercentage) > 0.1
  ) {
    currentTurns.value = newTurns
    totalTurns.value = newTotalTurns
    progressPercentage.value = newProgressPercentage
  }
}

const loadCard = async (card: Card) => {
  // console.log('[LOAD CARD]', card)
  if (!sampler.value || !card) return

  isLoadingCard.value = true
  // console.log(disc.value)
  try {
    await sampler.value.loadTrack(card.url_audio)
    if (disc.value) {
      // console.log('[DISC] Set Duration', sampler.value.duration)
      disc.value.setDuration(sampler.value.duration)
      updateTurns()
    }
  } finally {
    isLoadingCard.value = false
  }
}

const play = (position = 0) => {
  // console.log('[PLAY]')
  if (!disc.value || !sampler.value || !props.card) return

  sampler.value.play(position)
  disc.value.powerOn()
}

const pause = () => {
  // console.log('[PAUSE]')
  if (!disc.value || !sampler.value) return

  sampler.value.pause()
  disc.value.powerOff()
}

const togglePlay = () => {
  if (isPlaying.value) {
    pause()
  } else {
    // Reprendre la lecture à la position actuelle
    const currentPosition = disc.value?.secondsPlayed || 0
    play(currentPosition)
  }
}

// Nettoyage
const cleanup = () => {
  // console.log('[CLEANUP] Platine')
  if (disc.value) {
    disc.value.stop()
    disc.value.powerOff()
  }
  if (sampler.value) {
    sampler.value.pause()
  }
}

const handlePowerButtonClick = (e: MouseEvent) => {
  e.stopPropagation() // Empêcher la propagation de l'événement
  e.preventDefault() // Empêcher tout comportement par défaut
  togglePlay()
  return false // Empêcher tout autre comportement
}

const handleKeyDown = (e: KeyboardEvent) => {
  if (e.code === 'Space' || e.key === ' ' || e.keyCode === 32) {
    e.preventDefault() // Empêcher le défilement de la page
    togglePlay()
  }
}

// Initialisation du lecteur
onMounted(() => {
  isMounted.value = true
  if (discRef.value) {
    initPlatine(discRef.value)
    loadCard(props.card!)
  }

  // Ajouter l'écouteur d'événement clavier
  window.addEventListener('keydown', handleKeyDown)
})

// Nettoyage de l'écouteur d'événement
onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
  isMounted.value = false
  cleanup()
})

// Surveillance des changements de piste
watch(() => props.card, (newCard) => {
  // console.log('[WATCH] Card', newCard)
  if (newCard) {
    loadCard(newCard)
  }
})

</script>

<style lang="scss">
.platine {
  pointer-events: none;
  overflow: hidden;
  position: relative;
  width: 100%;
  height: 100%;
  padding: 20px;
}

.disc {
  pointer-events: auto;
  position: fixed;
  background-color: transparent;
  position: relative;
  aspect-ratio: 1;
  width: 100%;
  overflow: hidden;
  border-radius: 50%;
  cursor: grab;
  background-position: center;
  background-size: cover;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.4);

  .loading & {
    box-shadow: none;
  }
}

.turn-point {
  @apply absolute top-1/2 right-8 size-1/12 rounded-full bg-esyellow;
}

.disc.is-scratching {
  cursor: grabbing;
}

.power-button {
  border-radius: 999px;
  background-size: cover;
  background-position: center;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  width: 45%;
  aspect-ratio: 1/1;
  // background: no-repeat url(/favicon.svg) center center;
  background-size: 30%;
  border-radius: 50%;
  cursor: pointer !important;

  .power-logo {
    @apply size-1/2 bg-black rounded-full p-5;
  }

  .power-loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    border-radius: 50%;
  }
}

.disc-middle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 20px;
  height: 20px;
  background: rgb(26, 26, 26);
  border-radius: 50%;
}

.button {
  border-radius: 0;
  border: none;
  background: rgb(69, 69, 69);
  font-size: 0.75rem;
  padding: 0.4rem;
  color: #fff;
  line-height: 1.3;
  cursor: pointer;
  will-change: box-shadow;
  transition:
    box-shadow 0.2s ease-out,
    transform 0.05s ease-in;
}

.power.is-active {
  transform: translate(1px, 2px);
  color: red;
}

.button[disabled] {
  opacity: 0.5;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.bobine {
  @apply bg-slate-900 bg-opacity-50 backdrop-blur absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 rounded-full;
}

.debug {
  @apply fixed top-4 right-4 bg-slate-200 rounded-md p-2;
}
</style>
