/*
  ==============================================================================

    CMLSChorus.cpp
    Created: 1 May 2025 11:04:18pm
    Author:  Luigi

  ==============================================================================
*/

#include "CMLSChorus.h"

CMLSChorus::CMLSChorus() {
    freqRange = new juce::NormalisableRange<float>(LFO_MIN_FREQ, LFO_MAX_FREQ);
    depthRange = new juce::NormalisableRange<float>(LFO_MIN_DEPTH, LFO_MAX_DEPTH);
}

CMLSChorus::~CMLSChorus() {}

void CMLSChorus::reset() {
    delayLine1.reset();
    delayLine2.reset();
    dryWetMixer.reset();
}

void CMLSChorus::prepare(const juce::dsp::ProcessSpec& spec) {
    delayLine1.prepare(spec);
    delayLine2.prepare(spec);
    delayLine1.setMix(1.0f);
    delayLine2.setMix(1.0f);

    delayLine1.setCentreDelay(DELAY_CENTER);
    delayLine2.setCentreDelay(DELAY_CENTER);
    delayLine1.setRate(LFO_MIN_FREQ);
    delayLine1.setRate(LFO_MIN_FREQ + LFO_FREQ_DELTA);
    delayLine1.setDepth(LFO_MIN_DEPTH);
    delayLine2.setDepth(LFO_MIN_FREQ);

    dryWetMixer.prepare(spec);
    dryWetMixer.setMixingRule(juce::dsp::DryWetMixingRule::linear);
}

void CMLSChorus::process(const juce::dsp::ProcessContextReplacing<float>& context) {
	auto audioBlock = context.getOutputBlock();
	auto numChannels = audioBlock.getNumChannels();
    const auto numSamples = audioBlock.getNumSamples();

    // Initialize audio buffers
    juce::AudioBuffer<float> firstStageWetBuffer(numChannels, numSamples);
	juce::dsp::AudioBlock<float> firstStageWetBlock(firstStageWetBuffer);

	juce::AudioBuffer<float> secondStageWetBuffer(numChannels, numSamples);
	juce::dsp::AudioBlock<float> secondStageWetBlock(secondStageWetBuffer);

    // Calculate wet signal
    delayLine1.process(
        juce::dsp::ProcessContextNonReplacing<float>(audioBlock, firstStageWetBlock)
    );
	delayLine2.process(
		juce::dsp::ProcessContextNonReplacing<float>(audioBlock, secondStageWetBlock)
	);

    secondStageWetBlock += firstStageWetBlock;

	// Apply the dry/wet mix
    dryWetMixer.pushDrySamples(audioBlock);
    dryWetMixer.mixWetSamples(secondStageWetBlock);

    for (int channel = 0; channel < numChannels; ++channel) {
        for (int sample = 0; sample < numSamples; ++sample) {
            audioBlock.setSample(channel, sample, secondStageWetBlock.getSample(channel, sample));
        }
    }
}

void CMLSChorus::setDryWet(float value) {
    dryWetMixer.setWetMixProportion(value);
}

void CMLSChorus::setAmount(float value) {
    float freq = freqRange->convertFrom0to1(value);
    float depth = depthRange->convertFrom0to1(value);

    delayLine1.setRate(freq);
    delayLine2.setRate(freq + LFO_FREQ_DELTA); //+ LFO_FREQ_DELTA
    delayLine1.setDepth(depth);
    delayLine2.setDepth(depth);
}

const float CMLSChorus::getDryWet() {
	return this->dryWetProp;
}

const float CMLSChorus::getAmount() {
	return this->amount;
}