#pragma once

#include "ehs/EHS.h"
#include "ehs/Str.h"
#include "ehs/Vector.h"
#include "ehs/Array.h"
#include "ehs/DataType.h"

namespace ehs
{
	enum class AudioDeviceType
	{
		INPUT = 0x1,
		OUTPUT = 0x0,
		ALL = 0x2
	};

	enum class AudioDeviceState
	{
		ACTIVE = 0x1,
		DISABLED = 0x2,
		NOT_PRESENT = 0x4,
		UNPLUGGED = 0x8
	};

    class EHS_LIB_IO BaseAudioDevice
    {
	protected:
        AudioDeviceType type;
		DataType dataType;
		UInt_16 byteDepth;
		UInt_32 sampleRate;
		UInt_32 channels;
		UInt_32 period;
		UInt_32 latency;
		UInt_64 maxFrames;

    public:
        virtual ~BaseAudioDevice() = default;

        BaseAudioDevice();

        BaseAudioDevice(const BaseAudioDevice& device);

        BaseAudioDevice& operator=(const BaseAudioDevice& device);

		virtual void OpenStream();

		virtual void CloseStream();

    	virtual UInt_64 SendStream(const void *data, UInt_64 size);

    	virtual UInt_64 ReceiveStream(void *data, UInt_64 size);

		void BridgeStreams(BaseAudioDevice *input, UInt_64 frameBufferSize);

    	void BridgeStreams(UInt_64 frameBufferSize);

        AudioDeviceType GetType() const;

		void SetDataType(DataType newDataType);

		DataType GetDataType() const;

		UInt_8 GetByteDepth() const;

		UInt_16 GetBitDepth() const;

		void SetSampleRate(UInt_32 newSampleRate);

		UInt_32 GetSampleRate() const;

		void SetChannels(UInt_32 newChannels);

		UInt_16 GetChannels() const;

		UInt_32 GetFrameSize() const;

		void SetPeriod(UInt_32 newPeriod);

		UInt_32 GetPeriod() const;

		void SetLatency(UInt_32 newLatency);

		UInt_32 GetLatency() const;

		UInt_64 GetMaxFrames() const;

		virtual bool IsStreaming() const;

		virtual bool IsValid() const;

		/// Retrieves the default audio input/output device.
		/// @param [in] type The audio device type to retrieve.
		/// @param [out] device The default audio device.
		static BaseAudioDevice GetDefault(AudioDeviceType type);

		/// Retrieves a list of audio input/output devices.
		/// @param [in] type The audio device type to retrieve.
		/// @param [in] state The audio device state to retrieve.
		/// @param [out] devices The list of audio devices.
		static Array<BaseAudioDevice> Get(AudioDeviceType type, AudioDeviceState state);
    };
}