#pragma once

#include "../Parameters/DeepPluckParameters.h"

#include <juce_audio_basics/juce_audio_basics.h>

#include <array>
#include <vector>

namespace deeppluck
{
class DeepPluckDelay final
{
public:
    inline static constexpr std::array<double, 7> beatsPerDelay {
        1.0, 0.75, 0.5, 1.0 / 3.0, 0.375, 0.25, 1.0 / 6.0
    };

    void prepare (double sampleRate, int maximumBlockSize);
    void reset() noexcept;
    void setParameters (const DeepPluckParameterSnapshot& snapshot,
                        double lastValidTempoBpm) noexcept;
    void process (juce::AudioBuffer<float>& buffer, int startSample, int numSamples) noexcept;

    [[nodiscard]] bool isIdle() const noexcept;
    [[nodiscard]] double getTargetDelaySeconds() const noexcept;

private:
    static constexpr double maximumDelaySeconds = 3.0;
    static constexpr float maximumFeedback = 0.75f;
    static constexpr float tailSilenceThreshold = 1.0e-5f;
    static constexpr int requiredQuietBlocks = 8;
    static constexpr float wetCalibration = 0.60f;

    [[nodiscard]] float readDelayedSample (int channel, double delayInSamples) const noexcept;
    void clearSignalState() noexcept;

    std::array<std::vector<float>, 2> delayBuffer;
    std::array<float, 2> toneState {};
    juce::SmoothedValue<double, juce::ValueSmoothingTypes::Linear> delaySamples;
    juce::SmoothedValue<float, juce::ValueSmoothingTypes::Linear> feedback;
    juce::SmoothedValue<float, juce::ValueSmoothingTypes::Linear> toneCoefficient;
    juce::SmoothedValue<float, juce::ValueSmoothingTypes::Linear> mix;
    juce::SmoothedValue<float, juce::ValueSmoothingTypes::Linear> feedGain;
    juce::SmoothedValue<float, juce::ValueSmoothingTypes::Linear> bypassDry;
    double currentSampleRate = 44100.0;
    double targetDelaySeconds = 0.375;
    int writePosition = 0;
    int quietBlockCount = 0;
    int quietHoldSamples = 0;
    bool active = false;
    bool bypassed = true;
};
}
