// Copyright 2008-2026 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: GPL-2.0-or-later or MIT

#ifndef LVZ_AUDIOEFFECTX_H
#define LVZ_AUDIOEFFECTX_H

#include <lv2/atom/atom.h>
#include <lv2/core/lv2.h>
#include <lv2/urid/urid.h>

#include <cstdint>
#include <cstring>

class AudioEffect;

using audioMasterCallback = int (*)(int, int ver, int, int, int, int);

AudioEffect*
createEffectInstance(audioMasterCallback audioMaster);

enum LvzPinFlags {
	kLvzPinIsActive = 1 << 0,
	kLvzPinIsStereo = 1 << 1
};

struct LvzPinProperties {
	LvzPinProperties()
		: label{nullptr}
		, flags{0}
	{}
	char* label;
	int   flags;
};

enum LvzEventTypes {
	kLvzMidiType = 0
};

struct LvzEvent {
	int type;
};

struct LvzMidiEvent : public LvzEvent {
	char*   midiData;
	int32_t deltaFrames;
};

struct LvzEvents {
	int32_t    numEvents;
	LvzEvent** events;
};

#define DECLARE_LVZ_DEPRECATED(x) x

class AudioEffect
{
public:
	AudioEffect()          = default;
	virtual ~AudioEffect() = default;

	virtual void  setParameter(int32_t index, float value) = 0;
	virtual void  setParameterAutomated(int32_t index, float value) {}
	virtual float getParameter(int32_t index) = 0;

	virtual void masterIdle() {}
};

class AudioEffectX : public AudioEffect
{
public:
	AudioEffectX(audioMasterCallback audioMaster, int32_t progs, int32_t params)
		: URI{"NIL"}
		, uniqueID{"NIL"}
		, eventInput{nullptr}
		, midiEventType{0}
		, sampleRate{44100}
		, curProgram{0}
		, numInputs{0}
		, numOutputs{0}
		, numParams{params}
		, numPrograms{progs}
	{}

	virtual void process(const float** inputs, float** outputs, int32_t nframes)
	{}
	virtual void processReplacing(const float** inputs,
	                              float**       outputs,
	                              int32_t       nframes) = 0;

	void setMidiEventType(LV2_URID urid) { midiEventType = urid; }
	void setEventInput(const LV2_Atom_Sequence* seq) { eventInput = seq; }

	virtual int32_t processEvents(const LvzEvents* ev) { return 0; }

	virtual const char* getURI() { return URI; }
	virtual const char* getUniqueID() { return uniqueID; }
	virtual float       getSampleRate() { return sampleRate; }
	virtual int32_t     getNumInputs() { return numInputs; }
	virtual int32_t     getNumOutputs() { return numOutputs; }
	virtual int32_t     getNumParameters() { return numParams; }
	virtual int32_t     getNumPrograms() { return numPrograms; }

	virtual void getParameterDisplay(int32_t index, char* label) = 0;
	virtual void getParameterLabel(int32_t index, char* label)   = 0;
	virtual void getParameterName(int32_t index, char* label)    = 0;

	virtual void getProgramName(char* name) { name[0] = '\0'; }

	virtual bool getProgramNameIndexed(int32_t category,
	                                   int32_t index,
	                                   char*   name)
	{
		return false;
	}

	virtual int32_t canDo(const char* text) { return false; }
	virtual bool    canHostDo(const char* act) { return false; }
	virtual void    canMono() {}
	virtual void    canProcessReplacing() {}
	virtual void    isSynth() {}
	virtual void    wantEvents() {}

	virtual void setBlockSize(int32_t size) {}
	virtual void setNumInputs(int32_t num) { numInputs = num; }
	virtual void setNumOutputs(int32_t num) { numOutputs = num; }
	virtual void setSampleRate(float rate) { sampleRate = rate; }
	virtual void setProgram(int32_t prog) { curProgram = prog; }
	virtual void setProgramName(const char* name) {}
	virtual void setURI(const char* uri) { URI = uri; }
	virtual void setUniqueID(const char* id) { uniqueID = id; }

	virtual void suspend() {}
	virtual void resume() {}

	virtual void beginEdit(int32_t index) {}
	virtual void endEdit(int32_t index) {}

	virtual bool    getEffectName(char* name)    = 0;
	virtual bool    getVendorString(char* text)  = 0;
	virtual bool    getProductString(char* text) = 0;
	virtual int32_t getVendorVersion()           = 0;

protected:
	const char*              URI;
	const char*              uniqueID;
	const LV2_Atom_Sequence* eventInput;
	LV2_URID                 midiEventType;
	float                    sampleRate;
	int32_t                  curProgram;
	int32_t                  numInputs;
	int32_t                  numOutputs;
	int32_t                  numParams;
	int32_t                  numPrograms;
};

extern "C" {
LV2_SYMBOL_EXPORT AudioEffectX*
lvz_new_audioeffectx();
}

#endif // LVZ_AUDIOEFFECTX_H
