#ifndef __AUDIO_NULL_H
#define __AUDIO_NULL_H

#include <thread>
#include <chrono>
#include "Audio_Interface.h"

namespace Audio
{
class NullTimer
{
public:
    class Delegate
    {
    public:
        virtual void onTimerSignal(NullTimer& timer) = 0;
    };

protected:
    std::thread mWorkerThread;
    std::atomic_bool mShutdown = {false};
    Delegate* mDelegate = nullptr;
    std::chrono::milliseconds mInterval;    // Interval - wanted number of milliseconds
    std::chrono::microseconds mTail;        // Number of milliseconds that can be sent immediately to sink
    std::string mThreadName;

    void start();
    void stop();
    void run();
public:
    /* Interval is in milliseconds. */
    NullTimer(std::chrono::milliseconds interval, Delegate* delegate, const char* name = nullptr);
    ~NullTimer();
};

class NullInputDevice: public InputDevice, public NullTimer::Delegate
{
protected:
    void* mBuffer = nullptr;
    std::shared_ptr<NullTimer> mTimer;
    int64_t mTimeCounter = 0, mDataCounter = 0;
    void internalClose();

public:
    NullInputDevice();
    virtual ~NullInputDevice();

    bool open() override;
    void close() override;
    Format getFormat() override;

    void onTimerSignal(NullTimer& timer) override;
};

class NullOutputDevice: public OutputDevice, public NullTimer::Delegate
{
protected:
    std::shared_ptr<NullTimer> mTimer;
    void* mBuffer = nullptr;
    int64_t mDataCounter = 0, mTimeCounter = 0;

    void internalClose();
public:
    NullOutputDevice();
    virtual ~NullOutputDevice();

    bool open() override;
    void close() override;
    Format getFormat() override;

    void onTimerSignal(NullTimer& timer) override;
};

class NullEnumerator: public Enumerator
{
public:
    NullEnumerator();
    ~NullEnumerator();

    void open(int direction) override;
    void close() override;

    int count() override;
    std::tstring nameAt(int index) override;
    int idAt(int index) override;
    int indexOfDefaultDevice() override;
};

}

#endif
