#pragma once
/**
 * @file mirage_type.h
 * @brief 定义渲染元素和UI相关的基础类型
 *
 * 本文件定义了UI系统中用于渲染和布局的基础类型，包括：
 * - 时间相关类型和函数
 * - 对齐和布局枚举
 * - 几何和渲染结构体
 */

#include <chrono>
#include <Eigen/Eigen>

#include "color.h"
#include "enum_flags.h"

//-------------- 时间处理 --------------

/**
 * @brief 时间点类型
 */
using time_type = decltype(std::chrono::high_resolution_clock::now());

/**
 * @brief 时间段类型
 */
using duration_type = decltype(std::chrono::high_resolution_clock::now() - std::chrono::high_resolution_clock::now());

/**
 * @brief 获取当前时间点
 * @return 当前的高精度时间点
 */
inline time_type get_current_time() { return std::chrono::high_resolution_clock::now(); }

//-------------- 对齐和布局枚举 --------------

/**
 * @enum horizontal_alignment_t
 * @brief 水平对齐方式
 */
enum class horizontal_alignment_t {
	left,   ///< 左对齐
	center, ///< 居中对齐
	right,  ///< 右对齐
	stretch ///< 拉伸填充
};

/**
 * @enum vertical_alignment_t
 * @brief 垂直对齐方式
 */
enum class vertical_alignment_t {
	top,    ///< 顶部对齐
	center, ///< 居中对齐
	bottom, ///< 底部对齐
	stretch ///< 拉伸填充
};

/**
 * @enum visibility_t
 * @brief 组件可见性和交互行为的位标志
 */
enum class visibility_t : uint32_t {
	none                    = 0,                    ///< 无特定可见性设置
	collapsed               = 1 << 0,               ///< 不可见且不占用布局空间
	hidden                  = 1 << 1,               ///< 不可见但占用布局空间
	visible                 = 1 << 2,               ///< 可见且可交互
	self_hit_test_invisible = 1 << 3,               ///< 自身不可点击, 但子控件可点击
	hit_test_invisible      = 1 << 4,               ///< 整个组件树不可点击

	// 常用组合
	all                     = 0xFFFFFFFF,           ///< 所有可见性标志
	any_visible             = visible | self_hit_test_invisible | hit_test_invisible, ///< 任何可见状态
	any_invisible           = collapsed | hidden,   ///< 任何不可见状态
	any_hit_testable        = visible,              ///< 任何可命中测试状态
};
// 为visibility枚举启用位标志功能
DEFINE_ENUM_FLAGS(visibility_t)

/**
 * @enum orientation_t
 * @brief 组件方向
 */
enum class orientation_t {
	horizontal, ///< 水平方向
	vertical    ///< 垂直方向
};

//-------------- 文本流方向 --------------

/**
 * @enum flow_direction_t
 * @brief 文本和布局流动方向
 */
enum class flow_direction_t {
	left_to_right, ///< 从左到右
	right_to_left, ///< 从右到左
};

/**
 * @enum flow_direction_preference_t
 * @brief 流动方向首选项
 */
enum class flow_direction_preference_t {
	inherit,       ///< 继承父级设置
	culture,       ///< 根据当前文化设置
	left_to_right, ///< 强制从左到右
	right_to_left, ///< 强制从右到左
};

/**
 * @brief 全局默认流动方向设置
 */
inline static auto g_flow_direction = flow_direction_t::left_to_right;

//-------------- 几何和渲染结构体 --------------

/**
 * @struct rect_quad
 * @brief 表示矩形四个角点数据的模板结构
 *
 * @tparam T 角点数据类型
 *
 * 顺序为：左上、右上、左下、右下
 */
template<typename T>
struct rect_quad : std::array<T, 4> {
	/**
	 * @brief 默认构造函数
	 */
	rect_quad() : std::array<T, 4>() {
	}

	/**
	 * @brief 单值构造 - 所有角点使用相同值
	 * @param value 用于所有角点的值
	 */
	rect_quad(const T& value) : std::array<T, 4>{ value, value, value, value } {
	}

	/**
	 * @brief 左右构造 - 左侧角点共用一个值，右侧角点共用另一个值
	 * @param left 左侧角点的值
	 * @param right 右侧角点的值
	 */
	rect_quad(const T& left, const T& right) : std::array<T, 4>{ left, right, left, right } {
	}

	/**
	 * @brief 完整构造 - 指定所有四个角点的值
	 * @param left_top 左上角点的值
	 * @param right_top 右上角点的值
	 * @param left_bottom 左下角点的值
	 * @param right_bottom 右下角点的值
	 */
	rect_quad(const T& left_top, const T&    right_top,
	          const T& left_bottom, const T& right_bottom) : std::array<T, 4>{
		left_top,
		right_top,
		left_bottom,
		right_bottom
	} {
	}
};

//-------------- 特化类型 --------------

/** 表示矩形四个角颜色的类型 */
using rect_color = rect_quad<linear_color>;

/** 表示矩形四个角UV坐标的类型 */
using rect_uv = rect_quad<Eigen::Vector2f>;

/** 表示矩形四个角圆角半径的类型 */
using rect_round = rect_quad<float>;

/**
 * @brief 为rect_uv提供默认构造函数特化
 *
 * 创建标准纹理坐标(0,0)到(1,1)的UV矩形。
 */
template<>
inline rect_quad<Eigen::Vector2f>::rect_quad() : std::array<Eigen::Vector2f, 4>{
    Eigen::Vector2f{ 0, 0 },
    Eigen::Vector2f{ 1, 0 },
    Eigen::Vector2f{ 0, 1 },
    Eigen::Vector2f{ 1, 1 }
} {
}

/**
 * @struct mirage_vertex_param_t
 * @brief 顶点参数结构，用于存储渲染顶点的额外参数
 *
 * 提供多种构造方式，可以从各种容器类型或单个值构造
 */
struct mirage_vertex_param_t {
	//-------------- 构造函数 --------------

	/**
	 * @brief 默认构造函数
	 */
	mirage_vertex_param_t() = default;

	/**
	 * @brief 容器构造函数 - 从支持索引访问的容器构造
	 *
	 * 适用于std::array、rect_quad、Eigen::Vector等容器类型
	 */
	template<typename Container,
	         typename = std::enable_if_t<
		         !std::is_same_v<std::decay_t<Container>, mirage_vertex_param_t> &&
		         !std::is_arithmetic_v<std::decay_t<Container> >
	         >,
	         typename = decltype(std::declval<Container>()[0])> // 检查是否支持索引访问
	mirage_vertex_param_t(const Container& container) {
		try {
			x = static_cast<float>(container[0]);

			// 处理Eigen::Vector特别处理
			if constexpr (is_eigen_vector<Container>::value) {
				constexpr int N = Container::RowsAtCompileTime;
				y               = (N > 1) ? static_cast<float>(container[1]) : 0.0f;
				z               = (N > 2) ? static_cast<float>(container[2]) : 0.0f;
				w               = (N > 3) ? static_cast<float>(container[3]) : 0.0f;
			}
			// 处理rect_quad特别处理 - 它始终有4个元素
			else if constexpr (std::is_base_of_v<std::array<typename Container::value_type, 4>, Container>) {
				y = static_cast<float>(container[1]);
				z = static_cast<float>(container[2]);
				w = static_cast<float>(container[3]);
			}
			// 对于其他容器类型，尝试安全地获取剩余元素
			else if constexpr (has_size_method<Container>::value) {
				auto size = container.size();
				y         = (size > 1) ? static_cast<float>(container[1]) : 0.0f;
				z         = (size > 2) ? static_cast<float>(container[2]) : 0.0f;
				w         = (size > 3) ? static_cast<float>(container[3]) : 0.0f;
			}
			// 其他情况 - 尝试访问但可能会抛出异常
			else {
				try { y = static_cast<float>(container[1]); } catch (...) { y = 0.0f; }
				try { z = static_cast<float>(container[2]); } catch (...) { z = 0.0f; }
				try { w = static_cast<float>(container[3]); } catch (...) { w = 0.0f; }
			}
		} catch (...) {
			// 如果第一个元素访问失败，设置所有值为0
			x = y = z = w = 0.0f;
		}
	}

	/**
	 * @brief 单值构造函数
	 * @param val 用于x分量的值，其他分量设为0
	 */
	template<typename T,
	         typename = std::enable_if_t<std::is_arithmetic_v<std::decay_t<T> > > >
	mirage_vertex_param_t(T val) : x(val),
	                               y(0),
	                               z(0),
	                               w(0) {
	}

	/**
	 * @brief 两值构造函数
	 * @param x_val x分量
	 * @param y_val y分量
	 */
	template<typename T>
	mirage_vertex_param_t(T x_val, T y_val) : x(x_val),
	                                          y(y_val),
	                                          z(0),
	                                          w(0) {
	}

	/**
	 * @brief 三值构造函数
	 * @param x_val x分量
	 * @param y_val y分量
	 * @param z_val z分量
	 */
	template<typename T>
	mirage_vertex_param_t(T x_val, T y_val, T z_val) : x(x_val),
	                                                   y(y_val),
	                                                   z(z_val),
	                                                   w(0) {
	}

	/**
	 * @brief 四值构造函数
	 * @param x_val x分量
	 * @param y_val y分量
	 * @param z_val z分量
	 * @param w_val w分量
	 */
	template<typename T>
	mirage_vertex_param_t(T x_val, T y_val, T z_val, T w_val) : x(x_val),
	                                                            y(y_val),
	                                                            z(z_val),
	                                                            w(w_val) {
	}

	/**
	 * @brief 两容器构造函数 - 从两个容器构造，前两个元素到x,y，后两个元素到z,w
	 * @param a 第一个容器，提供x和y分量
	 * @param b 第二个容器，提供z和w分量
	 */
	template<typename A, typename B,
	         typename = decltype(std::declval<A>()[0]),
	         typename = decltype(std::declval<B>()[0])>
	mirage_vertex_param_t(const A& a, const B& b) : x(static_cast<float>(a[0])),
	                                                y(static_cast<float>(a[1])),
	                                                z(static_cast<float>(b[0])),
	                                                w(static_cast<float>(b[1])) {
	}

	//-------------- 辅助类型特征检测 --------------

	/**
	 * @brief 检测类型是否有tuple_size特征（用于固定大小容器）
	 */
	template<typename T, typename = void>
	struct has_tuple_size : std::false_type {
	};

	template<typename T>
	struct has_tuple_size<T, std::void_t<decltype(std::tuple_size_v<std::decay_t<T> >)> >
			: std::true_type {
	};

	/**
	 * @brief 检测类型是否有size()方法（用于动态大小容器）
	 */
	template<typename T, typename = void>
	struct has_size_method : std::false_type {
	};

	template<typename T>
	struct has_size_method<T, std::void_t<decltype(std::declval<T>().size())> >
			: std::true_type {
	};

	/**
	 * @brief 检测类型是否是Eigen向量
	 */
	template<typename T, typename = void>
	struct is_eigen_vector : std::false_type {
	};

	template<typename T>
	struct is_eigen_vector<T, std::void_t<decltype(T::RowsAtCompileTime)> >
			: std::true_type {
	};

	//-------------- 数据成员 --------------

	union {
		float a;
		float x;
	}; ///< 第一个分量，可以作为x或a访问
	union {
		float b;
		float y;
	}; ///< 第二个分量，可以作为y或b访问
	union {
		float c;
		float z;
	}; ///< 第三个分量，可以作为z或c访问
	union {
		float d;
		float w;
	}; ///< 第四个分量，可以作为w或d访问
};

/**
 * @struct mirage_vertex_t
 * @brief 完整的顶点结构，用于渲染
 *
 * 包含位置、UV坐标、颜色和额外参数
 */
struct mirage_vertex_t {
	Eigen::Vector2f       position; ///< 顶点位置
	Eigen::Vector2f       uv;       ///< 纹理坐标
	linear_color          color;    ///< 顶点颜色
	mirage_vertex_param_t param_a;  ///< 额外参数A
	mirage_vertex_param_t param_b;  ///< 额外参数B
	mirage_vertex_param_t param_c;  ///< 额外参数C
};

/**
 * @struct mirage_triangle_t
 * @brief 三角形索引结构
 *
 * 存储三个顶点的索引，用于构建三角形
 */
struct mirage_triangle_t {
	uint32_t indices[3]; ///< 三个顶点的索引
};
