<template>
  <div>
    <div v-if="error" class="error-message">
      {{ error }}
    </div>
    <AudioFileSelector @file-selected="onFileSelected" />
    <!-- Ramp Time Control -->
    <div class="ramp-time-control">
      <label for="rampTime">Ramp Time (ms):</label>
      <input
        id="rampTime"
        v-model="rampTime"
        type="range"
        min="100"
        max="50000"
        step="100"
      >
      <span>{{ rampTime }}ms</span>
    </div>
    <div class="gain-controller">
      <div v-for="frequency in frequencies" :key="frequency" class="frequency-control">
        <RNBOControlValue
          :center-frequency="frequency"
          @control-value-change="(value) => handleValueChange(value.frequency, value.value)"
        />
        <AudioTagWebAudio
          :ref="el => { if (el) audioElements[frequency] = el }"
          :src="audioSrc"
          :volume="currentVolumes[frequency]"
        />
        <div>
          Frequency: {{ frequency }}Hz
          <br>Gain Value (dB): {{ gainValuesDB[frequency] }}
          <br>Normalized: {{ normalizedVolumes[frequency] }}
          <br>Volume: {{ currentVolumes[frequency] }}
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, onUnmounted, reactive } from 'vue'
import AudioFileSelector from '../AudioFileSelector.vue'
import AudioTagWebAudio from './AudioTagWebAudio.vue'
import RNBOControlValue from './tests/ControlValues/RNBOControlValue.vue'
import { useAudioStore } from '~/stores/audio'

export default defineComponent({
  name: 'GainController',
  components: {
    RNBOControlValue,
    AudioTagWebAudio,
    AudioFileSelector
  },
  setup () {
    const logger = useNuxtApp().$logger
    logger.info('GainController setup')
    const audioStore = useAudioStore()
    logger.info('Got audioStore', audioStore)
    const audioSrc = ref(window.location.origin + '/sounds/lagoon.ogg')
    const rampTime = ref(25000)
    logger.info('Set rampTime', 25000)
    const frequencies = ref([63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000])
    logger.info('Set frequencies', { frequencies })
    const error = ref<string | null>(null)

    const gainValuesDB = reactive<Record<number, number>>({})
    const currentVolumes = reactive<Record<number, number>>({})
    const normalizedVolumes = reactive<Record<number, number>>({})
    const audioElements = reactive<Record<number, InstanceType<typeof AudioTagWebAudio>>>({})

    const rampIntervals: Record<number, ReturnType<typeof setInterval> | null> = {}

    const onFileSelected = (file: string) => {
      const fullPath = new URL(file, window.location.origin).toString()
      audioSrc.value = fullPath
      logger.info('User hat ein File ausgewählt ' + file)
      useNuxtApp().$logger.log({ audioElements })
      setTimeout(() => {
        audioStore.setPlaying(true)
      }, 250)
    }

    const calculateNormalizedVolume = (db: number): number => {
      const minDB = -12
      const maxDB = 2
      return (db - minDB) / (maxDB - minDB)
    }

    const rampVolume = (frequency: number, targetVolume: number, duration: number) => {
      const startVolume = currentVolumes[frequency] || 1
      const startTime = Date.now()
      const endTime = startTime + duration

      if (rampIntervals[frequency]) {
        clearInterval(rampIntervals[frequency]!)
      }

      rampIntervals[frequency] = setInterval(() => {
        const now = Date.now()
        if (now >= endTime) {
          currentVolumes[frequency] = targetVolume
          clearInterval(rampIntervals[frequency]!)
          rampIntervals[frequency] = null
          return
        }

        const progress = (now - startTime) / duration
        currentVolumes[frequency] = startVolume + (targetVolume - startVolume) * progress
      }, 50)
    }

    const handleValueChange = (frequency: number, value: number) => {
      logger.info('Change for ' + frequency + ' to ' + value)
      if (!isNaN(value)) {
        gainValuesDB[frequency] = value
        normalizedVolumes[frequency] = calculateNormalizedVolume(value)
        rampVolume(frequency, normalizedVolumes[frequency], rampTime.value)
      } else {
        useNuxtApp().$logger.log('value is not NaN', { value })
      }
    }

    onUnmounted(() => {
      Object.values(rampIntervals).forEach((interval) => {
        if (interval) { clearInterval(interval) }
      })
    })

    return {
      frequencies,
      gainValuesDB,
      currentVolumes,
      normalizedVolumes,
      audioElements,
      handleValueChange,
      error,
      onFileSelected,
      audioSrc,
      rampTime
    }
  }
})
</script>

<style scoped>
.error-message {
  color: red;
  font-weight: bold;
  padding: 10px;
  border: 1px solid red;
  border-radius: 5px;
  margin-bottom: 10px;
}
.ramp-time-control {
  margin-top: 20px;
}
.ramp-time-control input {
  width: 300px;
  margin: 0 10px;
}
.frequency-control {
  margin-bottom: 20px;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
}
</style>
