#include "windows_render_context.h"

#include <iostream>
#include <ranges>
#include "misc/angle_literals.h"

#include <windows.h>

#include "windows_render_state.h"

bool windows_mirage_render_context::init() {
    try {
        // 定义支持的特性级别（从高到低排序）
        D3D_FEATURE_LEVEL feature_levels[] = {
            D3D_FEATURE_LEVEL_11_1,
            D3D_FEATURE_LEVEL_11_0,
            D3D_FEATURE_LEVEL_10_1,
            D3D_FEATURE_LEVEL_10_0
        };

        // 设置设备创建标志
        // UINT device_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_SINGLETHREADED; // BGRA支持和单线程模式
        UINT device_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; // BGRA支持和单线程模式
#if DEBUG
        device_flags |= D3D11_CREATE_DEVICE_DEBUG; // 在Debug模式下启用调试层
#endif

        // 定义要尝试的驱动类型数组
        constexpr D3D_DRIVER_TYPE driver_types[] = {
            D3D_DRIVER_TYPE_HARDWARE, // 首选硬件加速
            D3D_DRIVER_TYPE_WARP,     // 其次是WARP软件渲染器
            D3D_DRIVER_TYPE_REFERENCE // 最后是参考软件渲染器
        };

        // 尝试按优先级创建设备
        HRESULT hr = E_FAIL;
        D3D_DRIVER_TYPE used_driver_type = D3D_DRIVER_TYPE_UNKNOWN;
        SetProcessDPIAware();

        for (const auto& driver_type : driver_types) {
            hr = D3D11CreateDevice(
                nullptr,             // 使用默认适配器
                driver_type,         // 驱动类型
                nullptr,             // 软件栅格化模块句柄(仅用于软件设备)
                device_flags,        // 设备创建标志
                feature_levels,      // 特性级别数组
                ARRAYSIZE(feature_levels), // 特性级别数量
                D3D11_SDK_VERSION,   // SDK版本
                &device,             // 输出设备
                &feature_level,      // 输出获取的特性级别
                &device_context      // 输出设备上下文
            );

            if (SUCCEEDED(hr)) {
                used_driver_type = driver_type;
                break;
            }
        }

        // 检查是否成功创建设备
        if (FAILED(hr)) {
            std::cerr << "mirage: " << "Failed to create D3D11 device with any driver type. HRESULT: 0x"
                    << std::hex << hr << std::dec << std::endl;
            cleanup();
            return false;
        }

        // **获取DXGI设备以访问适配器**
        IDXGIDevice* dxgi_device = nullptr;
        hr = device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgi_device));
        if (FAILED(hr)) {
            std::cerr << "mirage: Failed to get DXGI device. HRESULT: 0x" << std::hex << hr << std::dec << std::endl;
            cleanup();
            return false;
        }

        // **获取适配器**
        IDXGIAdapter* dxgi_adapter = nullptr;
        hr = dxgi_device->GetAdapter(&dxgi_adapter);
        dxgi_device->Release();

        if (FAILED(hr)) {
            std::cerr << "mirage: Failed to get DXGI adapter. HRESULT: 0x" << std::hex << hr << std::dec << std::endl;
            cleanup();
            return false;
        }

        // **获取适配器描述信息**
        DXGI_ADAPTER_DESC adapter_desc;
        hr = dxgi_adapter->GetDesc(&adapter_desc);
        if (FAILED(hr)) {
            std::wcerr << L"mirage: Failed to get DXGI Adapter description" << std::endl;
        }

        // **尝试获取最新的DXGI工厂版本 - 从最新的Factory6开始尝试**
        // Windows 10 Fall Creators Update (1709)或更高版本支持
        hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory6), reinterpret_cast<void**>(&dxgi_factory));
        if (SUCCEEDED(hr)) {
            std::cout << "mirage: Using IDXGIFactory6" << std::endl;
        } else {
            // 尝试Factory5 - Windows 10 Anniversary Update (1607)或更高版本
            hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory5), reinterpret_cast<void**>(&dxgi_factory));
            if (SUCCEEDED(hr)) {
                std::cout << "mirage: Using IDXGIFactory5" << std::endl;
            } else {
                // 尝试Factory4 - Windows 10初始版本
                hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory4), reinterpret_cast<void**>(&dxgi_factory));
                if (SUCCEEDED(hr)) {
                    std::cout << "mirage: Using IDXGIFactory4" << std::endl;
                } else {
                    // 尝试Factory3 - Windows 8.1
                    hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory3), reinterpret_cast<void**>(&dxgi_factory));
                    if (SUCCEEDED(hr)) {
                        std::cout << "mirage: Using IDXGIFactory3" << std::endl;
                    } else {
                        // 尝试Factory2 - Windows 8，支持FLIP模式交换链
                        hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgi_factory));
                        if (SUCCEEDED(hr)) {
                            std::cout << "mirage: Using IDXGIFactory2" << std::endl;
                        } else {
                            // 回退到基本Factory1 - Windows 7
                            hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgi_factory));
                            if (SUCCEEDED(hr)) {
                                std::cout << "mirage: Using IDXGIFactory1" << std::endl;
                            } else {
                                // 最后尝试原始Factory
                                hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgi_factory));
                                if (SUCCEEDED(hr)) {
                                    std::cout << "mirage: Using IDXGIFactory" << std::endl;
                                } else {
                                    std::cerr << "mirage: Failed to get any DXGI Factory" << std::endl;
                                    dxgi_adapter->Release();
                                    cleanup();
                                    return false;
                                }
                            }
                        }
                    }
                }
            }
        }

        // **检查是否支持撕裂(tearing)功能**
        BOOL allow_tearing = FALSE;
        // IDXGIFactory5及以上版本支持CheckFeatureSupport
        IDXGIFactory5* factory5 = nullptr;
        if (SUCCEEDED(dxgi_factory->QueryInterface(__uuidof(IDXGIFactory5), (void**)&factory5))) {
            if (SUCCEEDED(factory5->CheckFeatureSupport(
                DXGI_FEATURE_PRESENT_ALLOW_TEARING,
                &allow_tearing,
                sizeof(allow_tearing)))) {
                std::cout << "mirage: Tearing support: " << (allow_tearing ? "Yes" : "No") << std::endl;
            }
            factory5->Release();
        }
        tearing_supported = allow_tearing == TRUE;

        dxgi_adapter->Release();

        // 输出初始化成功信息
        std::cout << "mirage: D3D11 device created successfully" << std::endl;
        std::wcout << L"mirage: Using adapter: " << adapter_desc.Description << std::endl;

        // 输出驱动类型信息
        auto driver_type_str = "Unknown";
        switch (used_driver_type) {
            case D3D_DRIVER_TYPE_HARDWARE: driver_type_str = "Hardware";
                break;
            case D3D_DRIVER_TYPE_WARP: driver_type_str = "WARP";
                break;
            case D3D_DRIVER_TYPE_REFERENCE: driver_type_str = "Reference";
                break;
            default: ;
        }
        std::cout << "mirage: Using driver type: " << driver_type_str << std::endl;

        // 输出特性级别信息
        auto feature_level_str = "Unknown";
        switch (feature_level) {
            case D3D_FEATURE_LEVEL_11_1: feature_level_str = "11.1";
                break;
            case D3D_FEATURE_LEVEL_11_0: feature_level_str = "11.0";
                break;
            case D3D_FEATURE_LEVEL_10_1: feature_level_str = "10.1";
                break;
            case D3D_FEATURE_LEVEL_10_0: feature_level_str = "10.0";
                break;
            default: ;
        }
        std::cout << "mirage: Using feature level: " << feature_level_str << std::endl;

        return true;
    } catch (const std::exception& e) {
        std::cerr << "mirage: Exception during D3D11 initialization: " << e.what() << std::endl;
        cleanup();
        return false;
    }
}

// 资源清理函数
void windows_mirage_render_context::cleanup() {
	mirage_render_context::cleanup();
	// 安全释放COM接口
	sg_shutdown();
	if (device_context) {
		device_context->Release();
		device_context = nullptr;
	}
	if (device) {
		device->Release();
		device = nullptr;
	}
	if (dxgi_factory) {
		dxgi_factory->Release();
		dxgi_factory = nullptr;
	}
}

sg_environment windows_mirage_render_context::get_environment() {
	return {
		.d3d11 = {
			.device = device,
			.device_context = device_context
		}
	};
}

std::unique_ptr<mirage_window_state> windows_mirage_render_context::create_window_state(const Eigen::Vector2i& in_window_frame_size, void* in_window_handle) {
	auto state = std::make_unique<windows_render_state>();
	if (!state->init(device, dxgi_factory, in_window_frame_size, in_window_handle)) {
		return {};
	}
	return state;
}

mirage_render_context* mirage_create_render_context() { return new windows_mirage_render_context(); }
