#pragma once

#include "Array.h"
#include "Mat4.h"
#include "Ebene3D.h"

struct ID3D11Device;
struct ID3D11DeviceContext;
enum D3D_PRIMITIVE_TOPOLOGY;
struct ID3D11ShaderResourceView;
struct ID3D11RasterizerState;

namespace Framework
{
    class Shader; // Shader.h
    class DXVertexBuffer; // DXBuffer.h
    class DXIndexBuffer; // DXBuffer.h
    class Textur; // Textur.h
    class Model3D; // Model3D.h

    // Verwaltet die Zeichenfunktionen der Grafikkarte und wird zum Zeichnen von 3D Modelen verwendet. Wird von Bildschirm3D automatisch erzeugt.
    class Render3D
    {
    private:
        Mat4< float > matrixBuffer[ MAX_KNOCHEN_ANZ ];
        Mat4< float > view;
        Mat4< float > proj;
        Ebene3D< float > frustrum[ 6 ];
        Vec3< float > kamPos;
        ID3D11Device *device;
        ID3D11DeviceContext *context;
        ID3D11RasterizerState *texturRS;
        ID3D11RasterizerState *meshRS;
        Textur *defaultTextur;
        RCArray< RCArray< Shader > > *shader;
        Array< int > *shaderId;
        int lastObjektId;
        int lastTexturId;
        int ref;

    public:
        // Konstruktor
        __declspec( dllexport ) Render3D();
        // Destruktor
        __declspec( dllexport ) ~Render3D();
        // Setzt das Device, was zum zeichnen verwendet werden soll
        //  device: Das neue Device
        __declspec( dllexport ) void setDevice( ID3D11Device *device );
        // Setzt das Context Objekt, das zum Zeichnen verwendet werden soll
        //  context: das neue Conext Objekt
        __declspec( dllexport ) void setContext( ID3D11DeviceContext *context );
        // Setzt den aktuellen Shader. Er wird hinten an die Liste mit zuletzt verwendeten Shadern angef�gt
        //  listIndex: Der Index der Liste mit zuletzt verwendeten Shadern
        //  sh: Der Shader, der verwendet werden soll
        __declspec( dllexport ) void benutzeShader( int listIndex, Shader *sh );
        // Sprinkt in der Liste mit zuletzt benutzten Shadern zur�ck und benutzt wieder den dortiegen Shader
        //  listIndex: Der Index der Liste mit zuletzt verwe deten Shadern
        //  anz: Die Anzahl der Shader, die zur�ckgesprungen werden soll. Bei 0 passiert nichts
        __declspec( dllexport ) void releaseShader( int listIndex, int anz = 1 );
        // Setzt die View und Projektion Matrizen, die zum zeichnen verwendet werden sollen
        //  view: Die View Matrix der Kamera
        //  proj: Die Projektion Matrix der Kamera
        //  kamPos: Die Position der Kamera in der Welt
        __declspec( dllexport ) void setKameraMatrix( Mat4< float > &view, Mat4< float > &proj, Vec3< float > &kamPos );
        // Beginnt das Zeichnen eines bestimmten objektes
        //  zMdl: Das 3D Modelohne erh�hten Reference Counter
        __declspec( dllexport ) void beginnModel( Model3D *zMdl );
        // Zeichnet eine bestimmte struktur
        //  zIndexBuffer: Ein IndexBuffer, der auf verschiedene Vertices aus dem Vertex Buffer des Models zeigt. Ohne erh�hten Reference Counter
        //  textur: Ein Zeiger auf die Textur, die verwendet werden soll ohne erh�hten Reference Counter
        //  struktur: Die Struktur der angegebenen Indices, Beispiel: D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST oder D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ...
        __declspec( dllexport ) void draw( DXIndexBuffer *zIndexBuffer, Textur *zTextur, D3D_PRIMITIVE_TOPOLOGY struktur = (D3D_PRIMITIVE_TOPOLOGY)4 );
        // Gibt einen der aktuell verwendeten Shader zur�ck
        //  listIndex: Der Index der Lise mit Shadern, von denen der aktuell benutzte zur�ckgegeben werden soll
        __declspec( dllexport ) Shader *getShader( int listIndex ) const;
        // Gibt einen der aktuell verwendeten Shader ohne erh�hten Reference Counter zur�ck
        //  listIndex: Der Index der Lise mit Shadern, von denen der aktuell benutzte zur�ckgegeben werden soll
        __declspec( dllexport ) Shader *zShader( int listIndex ) const;
        // Gibt das momentan verwendete Device Objekt ohne erh�hten Reference Counter zur�ck
        __declspec( dllexport ) ID3D11Device *zDevice() const;
        // Gibt das momentan verwendete Context Objekt ohne erh�hten Reference Counter zur�ck
        __declspec( dllexport ) ID3D11DeviceContext *zContext() const;
        // �berpr�ft, ob eine Kugel in dem Sichtbaren Raum der Welt liegt und gezeichnet werden muss
        //  pos: Der Mittelpunkt der Kugel
        //  radius: Der Radius der Kugel
        //  dist: Einen Zeiger auf einen float, in dem das quadrat des Abstands zur Kammeraposition gespeichert wird, falls diese Funktion true zur�ckgiebt und der Zeiger nicht 0 ist
        __declspec( dllexport ) bool isInFrustrum( const Vec3< float > &pos, float radius, float *dist = 0 ) const;
        // Erh�ht den Reference Counting Z�hler.
        //  return: this.
        __declspec( dllexport ) Render3D *getThis();
        // Verringert den Reference Counting Z�hler. Wenn der Z�hler 0 erreicht, wird das Zeichnung automatisch gel�scht.
        //  return: 0.
        __declspec( dllexport ) Render3D *release();
    };
}