#include "shadow_map.h"

shadow_map::shadow_map()
    : depth_texture_(nullptr), depth_stencil_view_(nullptr), shader_resource_view_(nullptr), width_(0), height_(0) {}

shadow_map::~shadow_map() {
    shutdown();
}

bool shadow_map::initialize(ID3D11Device* device, int width, int height) {
    width_ = width;
    height_ = height;

    D3D11_TEXTURE2D_DESC texDesc = {};
    texDesc.Width = width;
    texDesc.Height = height;
    texDesc.MipLevels = 1;
    texDesc.ArraySize = 1;
    texDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
    texDesc.SampleDesc.Count = 1;
    texDesc.Usage = D3D11_USAGE_DEFAULT;
    texDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;

    if (FAILED(device->CreateTexture2D(&texDesc, nullptr, &depth_texture_)))
        return false;

    D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
    dsvDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    dsvDesc.Texture2D.MipSlice = 0;

    if (FAILED(device->CreateDepthStencilView(depth_texture_, &dsvDesc, &depth_stencil_view_)))
        return false;

    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
    srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
    srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    srvDesc.Texture2D.MipLevels = 1;

    if (FAILED(device->CreateShaderResourceView(depth_texture_, &srvDesc, &shader_resource_view_)))
        return false;

    return true;
}

void shadow_map::shutdown() {
    if (shader_resource_view_) { shader_resource_view_->Release(); shader_resource_view_ = nullptr; }
    if (depth_stencil_view_) { depth_stencil_view_->Release(); depth_stencil_view_ = nullptr; }
    if (depth_texture_) { depth_texture_->Release(); depth_texture_ = nullptr; }
}

void shadow_map::set_render_target(ID3D11DeviceContext* context) {
    context->OMSetRenderTargets(0, nullptr, depth_stencil_view_);
}

void shadow_map::clear_render_target(ID3D11DeviceContext* context, float depth) {
    context->ClearDepthStencilView(depth_stencil_view_, D3D11_CLEAR_DEPTH, depth, 0);
}

ID3D11ShaderResourceView* shadow_map::get_shader_resource_view() {
    return shader_resource_view_;
}