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

    PluginProcessor.h
    Created: 4 Nov 2025 6:20:37pm
    Author:  mickl

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

#pragma once
#include <JuceHeader.h>
#include "Shifter.h"

class WebViewPluginAudioProcessor : public AudioProcessor
{
public:
	//==============================================================================
	WebViewPluginAudioProcessor(AudioProcessorValueTreeState::ParameterLayout layout);

	//==============================================================================
	void prepareToPlay(double sampleRate, int samplesPerBlock) override;
	void releaseResources() override {}

	bool isBusesLayoutSupported(const BusesLayout& layouts) const override;

	void processBlock(AudioBuffer<float>&, MidiBuffer&) override;
	using AudioProcessor::processBlock;

	//==============================================================================
	const String getName() const override { return JucePlugin_Name; }

	bool acceptsMidi() const override { return false; }
	bool producesMidi() const override { return false; }
	bool isMidiEffect() const override { return false; }
	double getTailLengthSeconds() const override { return 0.0; }

	//==============================================================================
	int getNumPrograms() override { return 1; }
	int getCurrentProgram() override { return 0; }
	void setCurrentProgram(int) override {}
	const String getProgramName(int) override { return {}; }
	void changeProgramName(int, const String&) override {}

	//==============================================================================
	void getStateInformation(MemoryBlock& destData) override;
	void setStateInformation(const void* data, int sizeInBytes) override;
	bool new_midi = false;

	struct Parameters
	{
	public:
		explicit Parameters(AudioProcessorValueTreeState::ParameterLayout& layout)
		{
			sliderIds.push_back("formantPreserve");
			addToLayout<AudioParameterFloat>(layout,
				ParameterID{ "formantPreserve" },
				"Formant Preserve",
				NormalisableRange<float> {0.0f, 1.0f, .01f},
				.5f);

			sliderIds.push_back("autoTuneDepth");
			addToLayout<AudioParameterFloat>(layout,
				ParameterID("autoTuneDepth"),
				"AutoTune Depth",
				NormalisableRange<float> {0.0f, 1.1f, .01f},
				.5f);

			sliderIds.push_back("autoTuneSpeed");
			addToLayout<AudioParameterFloat>(layout,
				ParameterID("autoTuneSpeed"),
				"AutoTune Speed",
				NormalisableRange<float> {0.001f, 0.1f, .001f},
				.5f);

			sliderIds.push_back("harmonyMix");
			addToLayout<AudioParameterFloat>(layout,
				ParameterID("harmonyMix"),
				"Harmony Mix",
				NormalisableRange<float> {0.0f, 1.0f, .01f},
				.01f);

			sliderIds.push_back("portTime");
			addToLayout<AudioParameterFloat>(layout,
				ParameterID("portTime"),
				"Portamento Speed",
				NormalisableRange<float> {0.001f, 0.2f, .001f},
				.01f);

			sliderIds.push_back("freezePitch");
			addToLayout<AudioParameterFloat>(layout,
				ParameterID("freezePitch"),
				"Freeze pitch",
				NormalisableRange<float> {-12.0f, 12.0f, 1.00f},
				0.0f);

			sliderIds.push_back("freezeVolume");
			addToLayout<AudioParameterFloat>(layout,
				ParameterID("freezeVolume"),
				"Freeze Volume",
				NormalisableRange<float> {0.0f, 1.0f, .01f},
				0.5f);
			

			toggleIds.push_back("autoTuneEnabled");
			addToLayout<AudioParameterBool>(layout,
				ParameterID("autoTuneEnabled"),
				"AutoTune Enabled",
				false);

			toggleIds.push_back("freezeEnabled");
			addToLayout<AudioParameterBool>(layout,
				ParameterID("freezeEnabled"),
				"Freeze Enabled",
				false);
		}


		/*AudioParameterFloat& formantPreserve;
		AudioParameterFloat& autoTuneSpeed;
		AudioParameterFloat& autoTuneDepth;
		AudioParameterFloat& portTime;*/
		std::vector<juce::String> sliderIds;
		std::vector<juce::String> toggleIds;
		/*AudioParameterBool& mute;
		AudioParameterChoice& filterType;*/

	private:
		template <typename Param>
		static void add(AudioProcessorParameterGroup& group, std::unique_ptr<Param> param)
		{
			group.addChild(std::move(param));
		}

		template <typename Param>
		static void add(AudioProcessorValueTreeState::ParameterLayout& group, std::unique_ptr<Param> param)
		{
			group.add(std::move(param));
		}

		template <typename Param, typename Group, typename... Ts>
		static Param& addToLayout(Group& layout, Ts&&... ts)
		{
			auto param = std::make_unique<Param>(std::forward<Ts>(ts)...);
			auto& ref = *param;
			add(layout, std::move(param));
			return ref;
		}
	};

	Parameters parameters;
	AudioProcessorValueTreeState state;
	SpinLock midiLock;

	/*std::vector<int> spectrumData = [] { return std::vector<int>(256, 0.0f); }();
	SpinLock spectrumDataLock;

	SpectralBars spectralBars;*/

	dsp::LadderFilter<float> filter;
	Shifter shifter;

private:
	//==============================================================================
	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WebViewPluginAudioProcessor)

};