#include "windows_render_context.h"

#include <iostream>
#include <ranges>
#include <utf8.h>

#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,
					// 特性级别数组
					std::size(feature_levels),
					// 特性级别数量
					D3D11_SDK_VERSION,
					// SDK版本
					&device,
					// 输出设备
					&feature_level,
					// 输出获取的特性级别
					&device_context // 输出设备上下文
					);

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

		// 检查是否成功创建设备
		if (FAILED(hr)) {
			std::println(std::cerr, "mirage: 所有的 D3D11 设备类型都创建失败. HRESULT: 0x{:#06x}", hr);
			cleanup();
			return false;
		}

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

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

		if (FAILED(hr)) {
			std::println(std::cerr, "mirage: 无法获取 DXGI 适配器. HRESULT: 0x{:#06x}", hr);
			cleanup();
			return false;
		}

		// **获取适配器描述信息**
		DXGI_ADAPTER_DESC adapter_desc;
		hr = dxgi_adapter->GetDesc(&adapter_desc);
		if (FAILED(hr)) { std::println(std::cerr, "mirage: 无法获取 DXGI 适配器描述信息. HRESULT: 0x{:#06x}", hr); }

		struct dxgi_factory_func_data {
			IID         iid{};
			std::string name;
		};
#define DXGI_FUNC_DATA(dxgi_class) dxgi_factory_func_data{ __uuidof(dxgi_class), #dxgi_class }
		const std::array func_datas = {
			// **尝试获取最新的DXGI工厂版本 - 从最新的Factory6开始尝试**
			// Windows 10 Fall Creators Update (1709)或更高版本支持
			DXGI_FUNC_DATA(IDXGIFactory6),
			// 尝试Factory5 - Windows 10 Anniversary Update (1607)或更高版本
			DXGI_FUNC_DATA(IDXGIFactory5),
			// 尝试Factory4 - Windows 10初始版本
			DXGI_FUNC_DATA(IDXGIFactory4),
			// 尝试Factory3 - Windows 8.1
			DXGI_FUNC_DATA(IDXGIFactory3),
			// 尝试Factory2 - Windows 8，支持FLIP模式交换链
			DXGI_FUNC_DATA(IDXGIFactory2),
			// 回退到基本Factory1 - Windows 7
			DXGI_FUNC_DATA(IDXGIFactory1),
			// 最后尝试原始Factory
			DXGI_FUNC_DATA(IDXGIFactory),
		};
#undef DXGI_FUNC_DATA

		// **获取DXGI工厂**
		for (const auto& data: func_datas) {
			hr = dxgi_adapter->GetParent(data.iid, reinterpret_cast<void**>(&dxgi_factory));
			if (SUCCEEDED(hr)) {
				std::println(std::cout, "mirage: 使用 {}", data.name);
				break;
			}
		}
		if (FAILED(hr)) {
			std::println(std::cerr, "mirage: 无法获取 DXGI Factory. HRESULT: 0x{:#06x}", hr);
			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::println(std::cout, "mirage: 防撕裂支持: {}", (bool) allow_tearing); }
			factory5->Release();
		}
		tearing_supported = allow_tearing == TRUE;

		dxgi_adapter->Release();


		// 输出初始化成功信息
		std::println(std::cout, "mirage: 成功创建 D3D11 设备");
		{
			const std::u16string adapter_desc_str(reinterpret_cast<const char16_t*>(adapter_desc.Description));
			auto                 str = utf8::utf16to8(adapter_desc_str);
			std::println(std::cout, "mirage: 适配器名称: {}", str);
		}
		std::println(std::cout, "mirage: 适配器 VRAM: {} MB", adapter_desc.DedicatedVideoMemory / 1024 / 1024);

		// 输出驱动类型信息
		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::println(std::cout, "mirage: 使用驱动类型: {}", driver_type_str);

		// 输出特性级别信息
		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::println(std::cout, "mirage: 使用特性级别: {}", feature_level_str);

		return true;
	}
	catch (const std::exception& e) {
		std::println(std::cerr, "mirage: D3D11初始化失败: {}", e.what());
		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() {
	sg_environment env{};
	env.d3d11.device         = device;
	env.d3d11.device_context = device_context;
	return env;
}

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(); }
