#ifndef _HARDWARE_H_
#define _HARDWARE_H_

#include "lgi/common/TableLayout.h"

extern int MidiPacketSize(uint8_t *ptr, int len);

/// Interface class for receiving hardware events.
/// These functions should only ever be called from the hardware IO
/// thread (not the UI thread)
struct HardwareEvents : public LEventTargetI
{
	virtual ~HardwareEvents() {}

	virtual void SetThreadId(OsThreadId ThreadId) = 0;
	virtual void OnConnection(bool Connected) = 0;	
	virtual void OnButton(HwButton BtnType, int BtnIndex, bool Down, bool Held) = 0;
	virtual void OnParam(
		/// This index is unwrapped space: ie extern1-8
		int Index,
		int NewValue) = 0;
	virtual void OnMidiIn(uint8_t *Buf, size_t Length) = 0;
	virtual void OnTimer() = 0;
};

class Hardware : public LEventSinkI
{
	struct HardwarePriv *d;

public:
	enum ButtonModes
	{
		BtnNone,
		BtnMomentary,
		BtnLatching
	};
	
	enum ParamColourMode
	{
		ParamColourSingle,
		ParamColourHiRes,
		ParamColourRamp,
	};
	
	const char *GetClass() { return "Hardware"; }

	Hardware(HardwareEvents *Callback, Mc4Shared *shared);
	~Hardware();
	void Run();
	
	// Buttons API
	int GetButtons();
	bool SetButtonMode(int Index, ButtonModes Mode);

	// Continuous parameter API
	int GetParams();
	bool SetParamRange(int Index, int Min, int Max);
	bool SetParamValue(int Index, int Value);
	bool SetParamColour(int Index, LColour Colour, ParamColourMode Mode);

	// LED API
	int GetLeds();
	bool SetLed(int Index, LColour Col);

	// MIDI API
	bool SendMidi(uint8_t *Buf, size_t Length);
	
	// Impl
	bool SetTimer(int Ms = 0);
	void SetInterface(LView *Ui);
	LViewI *GetInterface();
	bool PostEvent(int Cmd, LMessage::Param a = 0, LMessage::Param b = 0);
};

#endif