#pragma once

#include "Betriebssystem.h"
#include "ReferenceCounter.h"

#ifdef WIN32
struct ID3D11Buffer;
struct D3D11_BUFFER_DESC;
struct ID3D11ShaderResourceView;
struct ID3D11Device;
struct ID3D11DeviceContext;
#endif

namespace Framework
{
    class DX12CopyCommandQueue;
    class DX12DirectCommandQueue;

    //! Eine Schnittstelle zwischen dem Arbeitsspeicher und dem Grafikspeicher
    class DXBuffer : public virtual ReferenceCounter
    {
    protected:
        void* data;
        bool changed;
        int len;
        int elLen;

    public:
        //! Konstruktor
        //! \param bind Der verwendungszweck des Buffers. Beispiel:
        //! D3D11_BIND_INDEX_BUFFER, D3D11_BIND_VERTEX_BUFFER. \param eLen Länge
        //! eines einzelnen Elements in Bytes
        DLLEXPORT DXBuffer(int eLen);
        //! Destruktor
        DLLEXPORT virtual ~DXBuffer();
        //! Setzt den geändert fläg, so das beim nächsten auruf von 'kopieren'
        //! die daten neu kopiert werden
        DLLEXPORT void setChanged();
        //! Ändert die länge des Buffers beim nächsten aufruf von 'kopieren'
        //! \param len Die Länge in Bytes
        DLLEXPORT void setLength(int len);
        //! Legt fest, was beim nächsten aufruf von 'kopieren' kopiert wird
        //! \param data Ein zeiger auf die Daten
        DLLEXPORT void setData(void* data);
        //! Kopiert die Daten in den Buffer, fals sie sich verändert haben
        DLLEXPORT virtual void copieren(int byteCount = -1) = 0;
        //! Gibt die Länge eines Elementes in bytes zurück
        DLLEXPORT int getElementLength() const;
        //! Gibt die Anzahl der Elemente im Buffer zurück
        DLLEXPORT int getElementAnzahl() const;
    };

#ifdef WIN32
    //! Ein Buffer mit Daten im Grafikspeicher
    class DX11Buffer : public DXBuffer
    {
    protected:
        D3D11_BUFFER_DESC* description;
        ID3D11Buffer* buffer;
        ID3D11Device* device;
        ID3D11DeviceContext* context;

    public:
        //! Konstruktor
        //! eSize: Die Länge eines Elementes in Bytes
        DLLEXPORT DX11Buffer(int eSize,
            ID3D11Device* device,
            ID3D11DeviceContext* context,
            int bindFlags);
        //! Destruktor
        DLLEXPORT virtual ~DX11Buffer();
        //! Kopiert die Daten in den Buffer, fals sie sich verändert haben
        DLLEXPORT void copieren(int byteCount = -1) override;
        //! Gibt den Buffer zurück
        DLLEXPORT ID3D11Buffer* zBuffer() const;
    };

    //! Ein Buffer von Indizes aus dem Buffer mit Eckpunkten, wovon immer drei
    //! ein Dreieck ergeben, das gezeichnet wird
    class DX11StructuredBuffer : public DX11Buffer
    {
    private:
        ID3D11ShaderResourceView* view;

    public:
        //! Konstruktor
        //! eSize: Die Länge eines Elementes in Bytes
        DLLEXPORT DX11StructuredBuffer(
            int eSize, ID3D11Device* device, ID3D11DeviceContext* context);
        //! Destruktor
        DLLEXPORT virtual ~DX11StructuredBuffer();
        //! Kopiert die Daten in den Buffer, fals sie sich verändert haben
        DLLEXPORT void copieren(int byteCount = -1) override;
        //! Gibt die verwendtete Shader Resource View zurück
        DLLEXPORT operator ID3D11ShaderResourceView*() const;
    };
#endif
} // namespace Framework