//
// Created by Administrator on 25-3-1.
//

#include "windows_render_context.h"

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

#include "core/window/render_window.h"
#include <windows.h>

#include "windows_window_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支持和单线程模式
#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;
		// 使用 DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2（推荐）
		if (SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) {
			std::cout << "mirage: " << "DPI awareness set to per-monitor aware v2" << std::endl;
		}

		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_ADAPTER_DESC adapter_desc;

		// 获取DXGI工厂以便后续创建交换链
		IDXGIAdapter* dxgi_adapter = nullptr;
		IDXGIDevice*  dxgi_device = nullptr;
		hr = device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgi_device));
		if (SUCCEEDED(hr)) {
			hr = dxgi_device->GetAdapter(&dxgi_adapter);
			if (SUCCEEDED(hr)) {
				hr = dxgi_adapter->GetDesc(&adapter_desc);
				if (FAILED(hr)) { std::wcerr << L"mirage: " << L"Failed to get DXGI Adapter description" << std::endl; }
				hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgi_factory));
				if (FAILED(hr)) { dxgi_factory = nullptr; }
				dxgi_adapter->Release();
			}
			dxgi_device->Release();
		}

		if (!dxgi_factory) {
			std::cerr << "Failed to get DXGI Factory" << std::endl;
			cleanup();
			return false;
		}

		// 输出初始化成功信息
		std::cout << "mirage: " << "D3D11 device created successfully" << std::endl;
		std::wcout << L"mirage: " << L"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::end_init() {
	mirage_render_context::end_init();
	elements.create_resources();
	elements.load_mirage_pipelines();
}

// 资源清理函数
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;
	}
}

void windows_mirage_render_context::tick(const duration_type& in_delta) {
	const auto& windows = mirage_window::get_windows();
	for (const auto& window: windows) {
		auto&   window_state = window->state;
		sg_pass pass{};
		pass.action.colors[0].load_action  = SG_LOADACTION_CLEAR;
		pass.action.colors[0].store_action = SG_STOREACTION_STORE;
		pass.action.colors[0].clear_value  = { 0.f, 0.f, 0.f, 1.0f };

		pass.action.depth.load_action  = SG_LOADACTION_CLEAR;
		pass.action.depth.store_action = SG_STOREACTION_DONTCARE;
		pass.action.depth.clear_value  = 1.0f;
		pass.swapchain                 = window_state->swapchain;

		sg_begin_pass(pass);
		sg_apply_viewport(0, 0, window_state->swapchain.width, window_state->swapchain.height, true);

		const auto& matrix = window->create_screen_to_dci_matrix();
		elements.set_projection_matrix(matrix);

		elements.begin_frame();

		// draw some triangles
		Eigen::Vector2f pos{ 0, 0 };
		Eigen::Vector2f pos2{ 200, 200 };
		Eigen::Vector2f size{ 200, 200 };
		elements.make_rounded_rect(
			pos,
			size,
			rect_color({ 1, 0, 0, 1 }, { 0, 1, 1, 1 }),
			{},
			rect_round({ 10, 20, 30, 40 }),
			45_deg,
			{ 0, 0 },
			{ 1, 1 }
		);
		elements.make_rounded_rect(
			pos2,
			size,
			rect_color({ 1, 1, 0, 1 })
		);

		elements.end_frame();
		sg_end_pass();
		sg_commit();

		window_state->present();
	}
}

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

bool windows_mirage_render_context::setup_surface(mirage_window* in_window) {
	auto state = std::make_unique<windows_window_state>();
	if (!state->init(device, dxgi_factory, in_window)) { return false; }

	in_window->state = std::move(state);
	return true;
}

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