"""Functions used to transform and manipulate audio for use by visualizers"""

from copy import copy
import numpy


def createSpectrumArray(
    component,
    completeAudioArray,
    sampleSize,
    smoothConstantDown,
    smoothConstantUp,
    scale,
    progressBarUpdate,
    progressBarSetText,
):
    lastProgress = 0
    lastSpectrum = None
    spectrumArray = {}
    for i in range(0, len(completeAudioArray), sampleSize):
        if component.canceled:
            break
        lastSpectrum = transformData(
            i,
            completeAudioArray,
            sampleSize,
            smoothConstantDown,
            smoothConstantUp,
            lastSpectrum,
            scale,
        )
        spectrumArray[i] = copy(lastSpectrum)

        progress = int(100 * (i / len(completeAudioArray)))
        if progress >= 100:
            progress = 100
        if progress == lastProgress:
            continue
        progressText = f"Analyzing audio: {str(progress)}%"
        progressBarSetText.emit(progressText)
        progressBarUpdate.emit(int(progress))
        lastProgress = progress
    return spectrumArray


def transformData(
    i,
    completeAudioArray,
    sampleSize,
    smoothConstantDown,
    smoothConstantUp,
    lastSpectrum,
    scale,
):
    if len(completeAudioArray) < (i + sampleSize):
        sampleSize = len(completeAudioArray) - i

    window = numpy.hanning(sampleSize)
    data = completeAudioArray[i : i + sampleSize][::1] * window
    paddedSampleSize = 2048
    paddedData = numpy.pad(data, (0, paddedSampleSize - sampleSize), "constant")
    spectrum = numpy.fft.fft(paddedData)
    sample_rate = 44100
    frequencies = numpy.fft.fftfreq(len(spectrum), 1.0 / sample_rate)

    y = abs(spectrum[0 : int(paddedSampleSize / 2) - 1])

    # filter the noise away
    # y[y<80] = 0

    with numpy.errstate(divide="ignore"):
        y = scale * numpy.log10(y)

    y[numpy.isinf(y)] = 0

    if lastSpectrum is not None:
        lastSpectrum[y < lastSpectrum] = y[
            y < lastSpectrum
        ] * smoothConstantDown + lastSpectrum[y < lastSpectrum] * (
            1 - smoothConstantDown
        )

        lastSpectrum[y >= lastSpectrum] = y[
            y >= lastSpectrum
        ] * smoothConstantUp + lastSpectrum[y >= lastSpectrum] * (1 - smoothConstantUp)
    else:
        lastSpectrum = y

    x = frequencies[0 : int(paddedSampleSize / 2) - 1]

    return lastSpectrum
