#pragma once
/**
 * @file mwindow.h
 * @brief 定义UI系统的窗口类
 *
 * 本文件定义了mirage_window类，作为UI系统的窗口容器，管理窗口的创建、
 * 操作、渲染和内容布局。窗口本身也是一个UI组件，可以包含其他组件。
 */

#include "widget/mwidget.h"
#include <memory>
#include <vector>
#include <functional>

#include "misc/delegates.h"

// 前向声明，减少依赖
class platform_window;
struct mirage_window_state;
struct mirage_paint_context;
struct hit_test_result;
struct wheel_event;

/**
 * @class mwindow
 * @brief UI系统的窗口类
 *
 * 表示一个可以包含UI组件的窗口。提供窗口创建、操作、样式设置和内容布局等功能。
 * 作为一个组件容器，窗口本身也是一个UI组件。
 */
class mwindow : public mwidget {
public:

    /**
     * @brief 析构函数
     */
    virtual ~mwindow() override;

    //-------------- 窗口操作 --------------
    /**
     * @brief 显示窗口
     */
    void show();

    /**
     * @brief 隐藏窗口
     */
    void hide();

    /**
     * @brief 关闭窗口
     */
    void close();

    /**
     * @brief 更新窗口状态、布局和渲染
     */
    void update();

    /**
     * @brief 获取平台窗口对象
     * @return 平台窗口指针
     */
    [[nodiscard]] auto get_platform_window() const -> platform_window*;

    //-------------- 窗口内容 --------------
    /**
     * @brief 设置窗口内容
     * @param content 要设置为内容的组件
     */
    void set_content(const std::shared_ptr<mwidget>& content);

    /**
     * @brief 获取窗口内容
     * @return 窗口内容组件
     */
    [[nodiscard]] auto get_content() const -> std::shared_ptr<mwidget>;

    //-------------- 几何与变换 --------------
    /**
     * @brief 获取DPI缩放比例
     * @return DPI缩放比例
     */
    [[nodiscard]] auto get_dpi_scale() const -> float override;

    /**
     * @brief 获取从本地坐标到屏幕坐标的变换
     * @return 变换矩阵
     */
    [[nodiscard]] auto get_local_to_screen_transform() const -> transform2d;

    /**
     * @brief 获取从本地坐标到窗口坐标的变换
     * @return 变换矩阵
     */
    [[nodiscard]] auto get_local_to_window_transform() const -> transform2d;

    /**
     * @brief 获取窗口在屏幕中的几何信息
     * @return 窗口几何信息
     */
    [[nodiscard]] auto get_window_geometry_in_screen() const -> geometry_t;

    /**
     * @brief 获取窗口在窗口中的几何信息
     * @return 窗口几何信息
     */
    [[nodiscard]] auto get_window_geometry_in_window() const -> geometry_t;

    //-------------- 失效处理 --------------
    /**
     * @brief 设置所有组件的失效标记
     */
    void invalidate_all();

    /**
     * @brief 标记矩形区域需要重绘
     * @param rect 需要重绘的区域
     */
    void invalidate_rect(const Eigen::Vector2f& rect);

    //-------------- 渲染和状态 --------------
    /**
     * @brief 获取窗口渲染状态
     * @return 渲染状态常量引用
     */
    [[nodiscard]] auto get_render_state() const -> const mirage_window_state&;

    /**
     * @brief 重建交换链
     */
    void rebuild_swapchain();

    /**
     * @brief 获取所有窗口
     * @return 窗口列表
     */
    [[nodiscard]] static auto get_all() -> const std::vector<std::weak_ptr<mwindow>>&;

    //-------------- 控件覆盖方法 --------------
    /**
     * @brief 计算窗口的期望大小
     * @param scale_multiplier 布局缩放系数
     * @return 窗口的期望大小
     */
    [[nodiscard]] auto compute_desired_size(float scale_multiplier) const -> Eigen::Vector2f override;

    /**
     * @brief 排列子组件
     * @param allotted_geometry 分配的几何区域
     */
    void arrange_children(const geometry_t& allotted_geometry) override;

    /**
     * @brief 绘制窗口及其内容
     * @param context 绘制上下文
     */
    void on_paint(mirage_paint_context& context) override;

    /**
     * @brief 获取窗口
     * @return 窗口指针
     */
    [[nodiscard]] auto get_window() const -> const mwindow* override { return this; }

    /**
     * @brief 获取窗口
     * @return 窗口指针
     */
    [[nodiscard]] auto get_window() -> mwindow* override { return this; }

    //-------------- 事件通知 --------------
    /** 窗口关闭事件委托 */
    multicast_delegate<mwindow*> on_close_delegate;

	static std::shared_ptr<mwindow> create(const Eigen::Vector2i& in_size, const std::wstring& in_title);
private:
	friend struct mwindow_make_shared_enabler;

    //-------------- 构造与析构 --------------
    /**
     * @brief 构造窗口
     * @param width 窗口初始宽度
     * @param height 窗口初始高度
     * @param title 窗口标题
     */
    mwindow(int32_t width, int32_t height, const wchar_t* title);

    //-------------- 内部实现 --------------
    // 前向声明窗口实现类
    class impl;
    // 实现的实例
    std::unique_ptr<impl> pimpl_;

    // 静态窗口集合，使用弱引用管理
    static std::vector<std::weak_ptr<mwindow>> windows_;
};
