<template>
  <div>
    <div v-if="error" class="error-message">
      {{ error }}
    </div>
    <AudioFileSelector @file-selected="onFileSelected" />
    <button @click="startAll">Start all Noises</button>
    <!-- Ramp Time Control -->
  </div>
  <div class="gain-controller">
    <div v-for="frequency in frequencies" :key="frequency" class="frequency-control">
      <RNBOControlValue
        :v-if="!isNaN(frequency)"
        :center-frequency="frequency"
        :status="audioSources[frequency] != null"
        @control-value-change="(value) => handleValueChange(value.frequency, value.value)"
      />
      <div :v-if="audioSources[frequency] != undefined && audioSources[frequency] != ''">
        <AudioTagWebAudio
          :ref="el => { if (el) audioElements[frequency] = el as any}"
          :src="audioSources[frequency] || ''"
          :volume="Number(currentVolumes[frequency])"
        />
      </div>
      <div>
        Frequency: {{ frequency }}Hz
        <br>Gain Value (dB): {{ gainValuesDB[frequency] }}
        <br>Normalized: {{ normalizedVolumes[frequency] }}
        <br>Volume: {{ currentVolumes[frequency] }}
      </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 { calculateNormalizedVolume } from '~/lib/AudioFunctions'
import { useAudioStore } from '~/stores/audio'
import tracksConfig from '~/tracks.config'

export default defineComponent({
  name: 'GainController',
  components: {
    RNBOControlValue,
    AudioTagWebAudio,
    AudioFileSelector
  },
  setup () {
    const logger = useNuxtApp().$logger as any
    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 audioSources = reactive<Record<number, string>>({})
    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 startAll = () => {
      const audioPaths = [tracksConfig['63_src'], tracksConfig['125_src'], tracksConfig['250_src'], tracksConfig['500_src'],
        tracksConfig['1000_src'], tracksConfig['2000_src'], tracksConfig['4000_src'], tracksConfig['8000_src'], tracksConfig['16000_src']]
      const recordsCount = Object.keys(audioElements).length
      if (recordsCount > 0) {
        for (let recordsCounter = 0; recordsCounter < recordsCount; recordsCounter++) {
          const audioElement = audioElements[frequencies.value[recordsCounter]]
          audioSources[frequencies.value[recordsCounter]] = `${window.location.origin}${encodeURI(audioPaths[recordsCounter])}`
        }
        useNuxtApp().$logger.log(audioSources[63])
      }
    }

    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) => {
      if (!isNaN(value)) {
        gainValuesDB[frequency] = value
        normalizedVolumes[frequency] = calculateNormalizedVolume(value)
        currentVolumes[frequency] = normalizedVolumes[frequency]
      } else {
        logger.warn('value is not a number, skip...', { value })
      }
    }

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

    return {
      frequencies,
      gainValuesDB,
      currentVolumes,
      normalizedVolumes,
      audioElements,
      handleValueChange,
      error,
      onFileSelected,
      audioSrc,
      rampTime,
      startAll,
      audioSources
    }
  }
})
</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>
