////////////////////////////////////////////////////////////////////////////////
// Filename: d3dclass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _D3DCLASS_H_
#define _D3DCLASS_H_


/////////////
// LINKING //
/////////////
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")


//////////////
// INCLUDES //
//////////////
#include "imguiManager.h"
#include "d3d11.h"
#include "font_shader_class.h"
#include "font_class.h"
#include "text_class.h"

using namespace DirectX;

////////////////////////////////////////////////////////////////////////////////
// Class name: d_3d_class
////////////////////////////////////////////////////////////////////////////////
class d_3d_class
{
public:
	/**
	 * @brief Default constructor for d_3d_class.
	 */
	d_3d_class();
	d_3d_class(const d_3d_class&);
	~d_3d_class();

	/**
	 * @brief Initializes the Direct3D device and related resources.
	 * 
	 * @param screenWidth Width of the screen.
	 * @param screenHeight Height of the screen.
	 * @param vsync Whether to enable vertical sync.
	 * @param hwnd Handle to the window.
	 * @param fullscreen Whether to run in fullscreen mode.
	 * @param screenDepth Depth of the screen.
	 * @param screenNear Near clipping plane distance.
	 * @return True if initialization was successful, false otherwise.
	 */
	virtual bool initialize(int, int, bool, HWND, bool, float, float);
	/**
	 * @brief Releases Direct3D resources.
	 */ 
	void shutdown();

	/**
	 * @brief Begins the rendering process for a new frame.
	 * 
	 * @param red Red component of the clear color.
	 * @param green Green component of the clear color.
	 * @param blue Blue component of the clear color.
	 * @param alpha Alpha component of the clear color.
	 */
	virtual void begin_scene(float, float, float, float);
	/**
	 * @brief Ends the rendering process for the current frame.
	 */
	virtual void end_scene();

	/**
	 * @brief Gets the Direct3D device.
	 * 
	 * @return Pointer to the ID3D11Device interface.
	 */
	ID3D11Device* get_device();
	/**
	 * @brief Gets the Direct3D device context.
	 * 
	 * @return Pointer to the ID3D11DeviceContext interface.
	 */
	ID3D11DeviceContext* get_device_context();
	//XMMATRIX get_projection_matrix(XMMATRIX& projectionMatrix);
	IDXGISwapChain* swap_chain;
	/**
	 * Get the swap chain associated with the Direct3D device.
	 * @return Pointer to the IDXGISwapChain interface.
	 */
	IDXGISwapChain* get_swap_chain();
	/**
	 * Resizes the swap chain to the specified width and height.
	 * @param width New width of the swap chain.
	 * @param height New height of the swap chain.
	 */
	void resize_swap_chain(int width, int height);
	/**
	 * @brief Sets the vertical sync state.
	 * 
	 * @param vsync True to enable vertical sync, false to disable.
	 */
	void set_vsync(bool vsync);

	/**
	 * Get the projection matrix.
	 * 
	 * @return XMMATRIX representing the projection matrix.
	 */
	XMMATRIX get_projection_matrix() const { return projection_matrix_; };
	/**
	 * Get the world matrix.
	 * 
	 * @return XMMATRIX representing the world matrix.
	 */
	XMMATRIX get_world_matrix() const { return world_matrix_;};
	/**
	 * Get the orthographic matrix.
	 * 
	 * @return XMMATRIX representing the orthographic matrix.
	 */
	XMMATRIX get_ortho_matrix() const { return ortho_matrix_; };

	/**
	 * Get the Video Card information.
	 * @param description Pointer to a character array to store the video card description.
	 * @param memory Reference to an integer to store the video card memory size.
	 */
	void get_video_card_info(char* description, int& memory);

	/**
	 * Set the render target to the back buffer.
	 */
	void set_back_buffer_render_target();
	/**
	 * Resets the viewport to the default settings.
	 */
	void reset_viewport();

	/**
	 * Release all Direct3D resources.
	 */
	void release_resources();
	/**
	 * Reset Direct3D resources based on the new width and height.
	 * @param newWidth 
	 * @param newHeight 
	 */
	void reset_resources(int newWidth, int newHeight);

	/**
	 * Turn on the Z-buffer to enable depth.
	 */
	void turn_z_buffer_on();
	/**
	 * Turn off the Z-buffer to disable depth.
	 */
	void turn_z_buffer_off();

	/**
	 * Turn on alpha blending for transparency effects.
	 */
	void enable_alpha_blending();
	/**
	 * Turn off alpha blending to disable transparency effects.
	 */
	void disable_alpha_blending();

private:
	bool vsync_enabled_;
	int video_card_memory_;
	char video_card_description_[128];
	ID3D11Device* device_;
	ID3D11DeviceContext* device_context_;
	ID3D11RenderTargetView* render_target_view_;
	ID3D11Texture2D* depth_stencil_buffer_;
	ID3D11DepthStencilState* depth_stencil_state_;
	ID3D11DepthStencilView* depth_stencil_view_;
	ID3D11RasterizerState* raster_state_;
	XMMATRIX projection_matrix_;
	XMMATRIX world_matrix_;
	XMMATRIX ortho_matrix_;
	D3D11_VIEWPORT viewport_;
	ID3D11DepthStencilState* depth_disabled_stencil_state_;
	ID3D11BlendState* alpha_enable_blending_state_;
	ID3D11BlendState* alpha_disable_blending_state_;
};

#endif