#pragma once

#include "Critical.h"
#include "Point.h"
#include "ReferenceCounter.h"

struct ID3D11Texture2D;
struct ID3D11ShaderResourceView;
struct ID3D11Device;
struct ID3D11DeviceContext;

namespace Framework
{
    class Image;       //! Image.h
    class Render3D;    //! Render3D.h
    class TextureList; //! TextureList.h
    class DX12CopyCommandQueue;
    class DX12DirectCommandQueue;

    //! Converts an image to a texture that can be passed to the graphics
    //! card for rendering
    class Texture : public virtual ReferenceCounter
    {
    protected:
        Image* bild;
        bool changed;
        Point lastGr;
        int id;

    public:
        //! Constructor
        DLLEXPORT Texture();
        //! Destructor
        DLLEXPORT virtual ~Texture();
        //! Sets a pointer to the image that contains the texture
        //! \param b The pointer to the image
        DLLEXPORT void setImageZ(Image* b);
        //! Sets the image that contains the texture by copying it
        //! \param b The image to copy
        DLLEXPORT void setImage(Image* b);
        //! Updates the texture. The pixels of the current image are copied
        //! to graphics memory
        DLLEXPORT virtual bool updateTextur() = 0;
        //! Returns true if updateTextur needs to be called
        DLLEXPORT virtual bool needsUpdate() const = 0;
        //! Returns a pointer to the image
        DLLEXPORT Image* getImage() const;
        //! Returns a pointer to the image without increased reference counter
        DLLEXPORT Image* zImage() const;
        //! Returns the id of the texture if it was registered in a TextureList.
        //! (see Framework::zTextureRegister())
        DLLEXPORT int getId() const;

        friend TextureList;
    };

    //! Converts an image to a texture that can be passed to the graphics
    //! card for rendering
    class DX9Texture : public Texture
    {
    public:
        //! Updates the texture. The pixels of the current image are copied
        //! to graphics memory
        DLLEXPORT virtual bool updateTextur() override;
        //! Returns true if updateTextur needs to be called
        DLLEXPORT virtual bool needsUpdate() const override;
    };

    class DX11Texture : public Texture
    {
    private:
        ID3D11Texture2D* txt;
        ID3D11ShaderResourceView* view;
        ID3D11Device* device;
        ID3D11DeviceContext* context;
        bool renderTarget;
        bool useMips;
        Critical& deviceLock;

    public:
        DLLEXPORT DX11Texture(ID3D11Device* device,
            ID3D11DeviceContext* context,
            Critical& deviceLock);
        DLLEXPORT ~DX11Texture();
        //! Updates the texture. The pixels of the current image are copied
        //! to graphics memory
        DLLEXPORT bool updateTextur() override;
        //! Returns true if updateTextur needs to be called
        DLLEXPORT bool needsUpdate() const override;
        //! Returns the used shader resource view
        DLLEXPORT operator ID3D11ShaderResourceView*() const;
        //! Returns the used texture
        DLLEXPORT operator ID3D11Texture2D*() const;
        //! specifies that this texture is used as a render target
        DLLEXPORT void setRenderTarget(bool rt);
        //! specifies if a mip map should be generated
        DLLEXPORT void setUseMips(bool useMips);
        //! copy the texture to an image
        DLLEXPORT void copyToImage(Image* zB);
    };
} // namespace Framework