#pragma once
#include "widget/mwidget.h"
#include "geometry/geometry.h"
#include "misc/mirage_type.h"

/**
 * @brief 为单个子部件布局的通用函数
 *
 * @param in_allotted_geometry 分配给容器的几何区域
 * @param child_widget 子部件
 * @param h_alignment 水平对齐方式
 * @param v_alignment 垂直对齐方式
 * @param margin 边距
 */
void arrange_single_child(
	const geometry_t& in_allotted_geometry,
	const std::shared_ptr<mwidget>& child_widget,
	horizontal_alignment_t h_alignment,
	vertical_alignment_t v_alignment,
	const margin_t& margin = margin_t() // 默认为空边距
);

template<orientation_t LayoutOrientation, typename SlotType>
void arrange_box_children(
	const geometry_t& in_allotted_geometry,
	float in_layout_scale_multiplier,
	visibility_t in_visibility_filter,
	const std::vector<SlotType>& child_slots,
	flow_direction_t flow_dir = flow_direction_t::left_to_right
){
	const auto& container_size = in_allotted_geometry.get_local_size();
	if (container_size.x() <= 0 || container_size.y() <= 0) {
		return;
	}

	// 确定主轴方向和是否反向
	constexpr bool is_horizontal = LayoutOrientation == orientation_t::horizontal;
	const bool is_reversed = flow_dir == flow_direction_t::right_to_left;

	// 第一轮：收集可见部件信息并计算自动尺寸
	struct slot_widget_info {
		std::shared_ptr<mwidget> widget;
		const SlotType*              slot;
		float                        size;
		float                        margin_start;       // 主轴起始边缘的margin
		float                        margin_end;         // 主轴结束边缘的margin
		float                        margin_cross_start; // 交叉轴起始边缘的margin
		float                        margin_cross_end;   // 交叉轴结束边缘的margin
	};

	std::vector<slot_widget_info> visible_widgets;
	float                         total_auto_size      = 0.0f;
	float                         total_stretch_factor = 0.0f;
	float                         total_margins        = 0.0f; // 主轴方向上所有边距的总和

	for (const auto& child_slot : child_slots) {
		const auto& widget = child_slot.get();
		// 无效部件或不可见部件跳过
		if (!widget)
			continue;

		if (!has_any_flag(widget->get_visibility(), in_visibility_filter))
			continue;

		const auto& margin = child_slot.margin();
		const float margin_left = margin.left;
		const float margin_right = margin.right;
		const float margin_top = margin.top;
		const float margin_bottom = margin.bottom;

		float margin_start, margin_end, margin_cross_start, margin_cross_end;
		if (is_horizontal) {
			margin_start = margin_left;
			margin_end = margin_right;
			margin_cross_start = margin_top;
			margin_cross_end = margin_bottom;
		} else {
			margin_start = margin_top;
			margin_end = margin_bottom;
			margin_cross_start = margin_left;
			margin_cross_end = margin_right;
		}

		total_margins += margin_start + margin_end;
		slot_widget_info info{ widget,
		                       &child_slot,
		                       0.0f,
		                       margin_start,
		                       margin_end,
		                       margin_cross_start,
		                       margin_cross_end
		};

		const auto& size_attr = child_slot.size();
		if (size_attr.is_auto_size()) {
			// 缓存部件的期望大小
			widget->cache_desired_size(in_layout_scale_multiplier);
			const auto& desired_size = widget->get_desired_size().value();

			info.size = is_horizontal ? desired_size.x() : desired_size.y();
			total_auto_size += info.size;
		} else {
			total_stretch_factor += size_attr.stretch();
		}

		visible_widgets.push_back(info);
	}

	if (visible_widgets.empty())
		return;

	// 计算拉伸部件的可用空间（需要减去所有margin）
	const float container_primary_size = is_horizontal ? container_size.x() : container_size.y();
	const float remaining_space = std::max(0.0f, container_primary_size - total_auto_size - total_margins);

	// 第二轮：计算拉伸部件的最终尺寸
	for (auto& info : visible_widgets) {
		const auto& size_attr = info.slot->size();
		if (!size_attr.is_auto_size()) {
			const float stretch_factor = size_attr.stretch();
			if (total_stretch_factor > 0.0f) {
				info.size = remaining_space * (stretch_factor / total_stretch_factor);
			} else {
				info.size = 0.0f;
			}
		}
	}

	// 第三轮：排列部件
	float position = 0.0f;

	if (is_reversed)
		std::reverse(visible_widgets.begin(), visible_widgets.end());

	for (const auto& info : visible_widgets) {
		position += info.margin_start;

		Eigen::Vector2f pos = Eigen::Vector2f::Zero();
		Eigen::Vector2f size = container_size;

		if (is_horizontal) {
			if (is_reversed)
				pos.x() = container_primary_size - position - info.size;
			else
				pos.x() = position;

			pos.y() += info.margin_cross_start;
			size.x() = info.size;
			size.y() -= info.margin_start + info.margin_end;
		} else {
			if (is_reversed)
				pos.y() = container_primary_size - position - info.size;
			else
				pos.y() = position;

			pos.x() += info.margin_cross_start;
			size.x() -= info.margin_start + info.margin_end;
			size.y() = info.size;
		}

		const auto& child_geometry = in_allotted_geometry.make_child(pos, size);
		info.widget->set_geometry(child_geometry);
		info.widget->arrange_children(child_geometry);

		position += info.size + info.margin_end;
	}
}

// 计算水平或垂直框的期望大小
template<orientation_t LayoutOrientation, typename SlotType>
Eigen::Vector2f compute_box_desired_size(const std::vector<SlotType>& child_slots) {
    Eigen::Vector2f desired_size = Eigen::Vector2f::Zero();

    for (const auto& slot : child_slots) {
        const auto& widget = slot.get();
        if (widget && has_any_flag(widget->get_visibility(), visibility_t::any_visible)) {
        	widget->cache_desired_size(widget->get_dpi_scale());
            Eigen::Vector2f widget_desired_size = widget->get_desired_size().value();
            if (LayoutOrientation == orientation_t::horizontal) {
                desired_size.x() += widget_desired_size.x();
                desired_size.y() = std::max(desired_size.y(), widget_desired_size.y());
            } else {
                desired_size.x() = std::max(desired_size.x(), widget_desired_size.x());
                desired_size.y() += widget_desired_size.y();
            }
        }
    }

    return desired_size;
}