#include "mwindow.h"
#include "geometry/dpi_helper.h"
#include "platform_window/platform_window.h"
#include "render/render_context.h"

/**
 * @brief 鼠标状态结构体
 */
struct mouse_state {
    Eigen::Vector2f position = Eigen::Vector2f::Zero();
    Eigen::Vector2f press_position = Eigen::Vector2f::Zero();
    time_type press_time{};
    time_type last_click_time{};
    std::weak_ptr<mwidget> hover_widget;
    std::weak_ptr<mwidget> hit_widget;

    void reset() {
        position = Eigen::Vector2f::Zero();
        press_position = Eigen::Vector2f::Zero();
        press_time = {};
        hover_widget.reset();
        hit_widget.reset();
    }
};

/**
 * @brief 渲染状态结构体
 */
struct render_state {
    bool is_layout_changed{false};
    bool needs_repaint{true};
};

/**
 * @class mwindow::impl
 * @brief 窗口实现类
 */
class mwindow::impl {
public:
    impl(mwindow* owner, int32_t width, int32_t height, const wchar_t* title)
        : owner_(owner) {
        // 创建平台窗口
        platform_window_ = std::make_unique<platform_window>(width, height, title);

        // 设置窗口事件回调
        platform_window_->on_resize_delegate.add_raw(this, &impl::on_resize);
        platform_window_->on_mouse_move_delegate.add_raw(this, &impl::process_mouse_move);
        platform_window_->on_mouse_button_down_delegate.add_raw(this, &impl::process_mouse_button_down);
        platform_window_->on_mouse_button_up_delegate.add_raw(this, &impl::process_mouse_button_up);
        platform_window_->on_mouse_wheel_delegate.add_raw(this, &impl::process_mouse_wheel);
        platform_window_->on_mouse_leave_delegate.add_raw(this, &impl::process_mouse_leave);
        platform_window_->on_mouse_button_dbl_delegate.add_raw(this, &impl::process_mouse_button_dbl);

        // 创建窗口渲染状态
        const auto& window_frame_size = platform_window_->get_window_frame_size();
        window_state_                 = mirage_render_context::get()->create_window_state(
		        window_frame_size,
		        platform_window_->get_window_handle());

        // 初始化渲染上下文
        paint_context_.init(window_frame_size);

        // 设置初始几何信息
        const transform2d identity;
        owner_->geometry_ = { window_frame_size.cast<float>(), identity, identity };
    }

    ~impl() {
        platform_window_->close();
    }

    // 窗口操作
    void show() {
        platform_window_->show();
    }

    void hide() {
        platform_window_->hide();
    }

    void close() {
        owner_->on_close_delegate.broadcast(owner_);
        platform_window_->close();
    }

    // 更新函数
    void update() {
        update_layout();
        update_hit_test();
        update_paint();
    }

    void update_layout() {
        layout_all(owner_);
    }

    void update_hit_test() {
        if (!render_state_.is_layout_changed)
            return;

        render_state_.is_layout_changed = false;
        process_mouse_move(mouse_.position);
    }

    void update_paint() {
        if (!platform_window_->is_visible())
            return;

        if (!owner_->has_invalidate_reason(invalidate_reason::paint) && !render_state_.needs_repaint)
            return;

        render_state_.needs_repaint = false;

        // 设置渲染通道属性
        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);

        // 执行控件绘制
        paint_context_.begin_frame();
        paint_all(owner_);
        paint_context_.end_frame();

        // 结束渲染并提交
        sg_end_pass();
        sg_commit();

        // 显示渲染结果并清除重绘标记
        window_state_->present();
        owner_->unset_invalid_reason(invalidate_reason::paint);
    }

    // 几何与变换
    float get_dpi_scale() const {
        return dpi_helper::get_global_scale() * platform_window_->get_window_dpi_scale();
    }

    transform2d get_local_to_screen_transform() const {
        return transform2d(
            platform_window_->get_window_position().cast<float>(),
            0,
            { get_dpi_scale(), get_dpi_scale() }
        );
    }

    transform2d get_local_to_window_transform() const {
        return transform2d(
            {0, 0},
            0,
            { get_dpi_scale(), get_dpi_scale() }
        );
    }

    geometry_t get_window_geometry_in_screen() const {
        const auto& local_to_screen = get_local_to_screen_transform();
        return { platform_window_->get_window_frame_size().cast<float>(), local_to_screen, {} };
    }

    geometry_t get_window_geometry_in_window() const {
        const auto& local_to_window = get_local_to_window_transform();
        return { platform_window_->get_window_frame_size().cast<float>(), local_to_window, local_to_window };
    }

    // 内容管理
    void set_content(const std::shared_ptr<mwidget>& widget) {
        content_widget_ = widget;
        if (widget) {
            widget->init();
            widget->set_parent(owner_->shared_from_this());
            owner_->invalidate(invalidate_reason::all);
        }
    }

    std::shared_ptr<mwidget> get_content() const {
        return content_widget_;
    }

	    // 失效处理
    void invalidate_all() {
        invalidate_recursive(owner_, invalidate_reason::all);
        render_state_.needs_repaint = true;
    }

    void invalidate_rect(const Eigen::Vector2f& rect) {
        // 实际的实现可以跟踪脏区域，这里简化为完全重绘
        render_state_.needs_repaint = true;
        owner_->invalidate(invalidate_reason::paint);
    }

    // 辅助函数
    void invalidate_recursive(mwidget* widget, invalidate_reason reason) {
        if (!widget) return;

        widget->invalidate(reason);
        for (const auto& child : widget->get_children()) {
            invalidate_recursive(child.get(), reason);
        }
    }

    void rebuild_swapchain() {
        window_state_->rebuild_swapchain(platform_window_->get_window_frame_size());
        render_state_.needs_repaint = true;
    }

    // 布局与绘制
    void paint_all(mwidget* widget) {
        if (!widget || !is_visible_in_viewport(widget)) {
            return;
        }

        // 设置渲染上下文并绘制当前控件
        paint_context_.set_geometry(widget->get_geometry());
        widget->on_paint(paint_context_);

        // 递归绘制所有子控件
        for (const auto& child : widget->get_children()) {
            paint_all(child.get());
        }
    }

    bool is_visible_in_viewport(mwidget* widget) {
        if (!widget) return false;

        // 简化版视口测试，实际实现应检查裁剪区域重叠
        const auto& geo = widget->get_geometry();
        const auto& window_size = platform_window_->get_window_frame_size().cast<float>();
    	const auto& size = geo.get_local_size();
    	const auto& pos = geo.get_window_position();

        // 检查是否完全在视口外
        return !(size.x() <= 0.0f || size.y() <= 0.0f ||
                pos.x() >= window_size.x() ||
                pos.y() >= window_size.y() ||
                pos.x() + size.x() <= 0.0f ||
                pos.y() + size.y() <= 0.0f);
    }

    void layout_all(mwidget* widget) {
        if (!widget) return;

        if (widget->has_invalidate_reason(invalidate_reason::layout)) {
            widget->arrange_children(widget->get_geometry());
            widget->unset_invalid_reason(invalidate_reason::layout);
            render_state_.is_layout_changed = true;
        }

        for (const auto& child : widget->get_children()) {
            layout_all(child.get());
        }
    }

    // 事件处理
    void on_resize(const Eigen::Vector2i& size) {
        // 更新交换链尺寸
        window_state_->swapchain.width = size.x();
        window_state_->swapchain.height = size.y();

        // 更新绘制上下文
        paint_context_.update_projection_matrix(size);

        // 更新窗口几何信息
        const transform2d identity;
        owner_->geometry_ = { size.cast<float>(), identity, identity };

        // 更新内容布局
        if (content_widget_) {
            const geometry_t new_geometry(size.cast<float>(), identity, identity);
            content_widget_->set_geometry(new_geometry);
        }

        // 标记需要重绘和重建交换链
        invalidate_all();
        rebuild_swapchain();
    }

    void process_mouse_move(const Eigen::Vector2f& window_pos) {
        // 更新最后鼠标位置
        mouse_.position = window_pos;

        // 执行命中测试，查找鼠标位置下的控件
        const auto& result = perform_hit_test(window_pos, [this](mwidget* widget, const Eigen::Vector2f& local_pos) {
            return widget->on_mouse_move(local_pos);
        });

        // 如果悬停控件没有变化，直接返回
        std::shared_ptr<mwidget> hover_widget = result.widget;
        std::shared_ptr<mwidget> last_hover = mouse_.hover_widget.lock();

        if (last_hover == hover_widget) {
            return;
        }

        // 处理鼠标离开上一个悬停控件
        if (last_hover) {
            last_hover->on_mouse_leave();
        }

        // 更新悬停控件并触发鼠标进入事件
        mouse_.hover_widget = hover_widget;
        if (hover_widget) {
            hover_widget->on_mouse_enter();
        }
    }

    void process_mouse_button_down(const Eigen::Vector2f& window_pos, mouse_button button) {
        // 执行命中测试，找出鼠标位置下的控件
        const auto& result = perform_hit_test(window_pos, [button](mwidget* widget, const Eigen::Vector2f& local_pos) {
            return widget->on_mouse_button_down(local_pos, button);
        });

        // 记录点击状态信息
        mouse_.hit_widget = result.widget;
        mouse_.press_time = get_current_time();
        mouse_.press_position = window_pos;
    }

    void process_mouse_button_up(const Eigen::Vector2f& window_pos, mouse_button button) {
        // 执行命中测试，找出鼠标位置下的控件
        const auto& hit_result = perform_hit_test(window_pos, [button](mwidget* widget, const Eigen::Vector2f& local_pos) {
            return widget->on_mouse_button_up(local_pos, button);
        });

        const auto& hit_widget = hit_result.widget;
        const auto& widget_local_pos = hit_result.widget_space_pos;

        // 获取之前点击的控件
        std::shared_ptr<mwidget> pressed_widget = mouse_.hit_widget.lock();

        // 如果没有点击到任何控件，重置状态并返回
        if (!pressed_widget) {
            mouse_.hit_widget.reset();
            return;
        }

        // 定义点击判定阈值
        constexpr auto CLICK_TIME_THRESHOLD = std::chrono::milliseconds(200);    // 单次点击最大持续时间
        constexpr float CLICK_DISTANCE_THRESHOLD = 5.0f;  // 点击位置容差

        // 计算按下到释放的时间间隔
        const auto press_duration = get_current_time() - mouse_.press_time;

        // 计算与按下位置的距离
        const float distance = (window_pos - mouse_.press_position).norm();

        // 只处理有效点击(时间短且位置接近)
        if (press_duration < CLICK_TIME_THRESHOLD && distance < CLICK_DISTANCE_THRESHOLD) {
            pressed_widget->on_click(widget_local_pos, button);
            mouse_.last_click_time = get_current_time();
        }
    }

    void process_mouse_button_dbl(const Eigen::Vector2f& window_pos, mouse_button button) {
        std::shared_ptr<mwidget> hover_widget = mouse_.hover_widget.lock();
        if (hover_widget) {
            hover_widget->on_double_click(window_pos, button);
        }
    }

    void process_mouse_wheel(const Eigen::Vector2f& window_pos, wheel_event wheel_event) {
        std::shared_ptr<mwidget> hover_widget = mouse_.hover_widget.lock();
        if (hover_widget) {
            hover_widget->on_mouse_wheel(window_pos, wheel_event);
        }
    }

    void process_mouse_leave() {
        std::shared_ptr<mwidget> hover_widget = mouse_.hover_widget.lock();
        if (hover_widget) {
            hover_widget->on_mouse_leave();
        }
        mouse_.hover_widget.reset();
    }

    // 命中测试
    hit_test_result perform_hit_test(
        const Eigen::Vector2f& window_pos,
        const std::function<hit_test_handle(mwidget*, const Eigen::Vector2f&)>& hit_func) const
    {
        if (!content_widget_) {
            return {};
        }
        return perform_hit_test(content_widget_.get(), window_pos, hit_func);
    }

    hit_test_result perform_hit_test(
        mwidget* widget,
        const Eigen::Vector2f& window_pos,
        const std::function<hit_test_handle(mwidget*, const Eigen::Vector2f&)>& hit_func) const
    {
        if (!widget) {
            return {};
        }

        const auto& widget_geo = widget->get_geometry();

        // 检查点是否在控件区域内
        auto widget_local_pos = widget_geo.is_under_location(window_pos);
        if (!widget_local_pos) {
            return {};
        }

        // 先递归查找子控件（从前到后）
        // 这样可以优先处理上层控件的点击
        for (auto it = widget->get_children().rbegin(); it != widget->get_children().rend(); ++it) {
            if (const auto& result = perform_hit_test(it->get(), window_pos, hit_func)) {
                return result;
            }
        }

        // 如果控件可以命中测试，执行命中测试回调
        if (widget->can_hit_test()) {
            const auto& widget_pos = widget_local_pos.value();
            if (hit_func(widget, widget_pos)) {
                return { widget->shared_from_this(), widget_pos };
            }
        }

        return {};
    }

    // 访问器
    platform_window* get_platform_window() const {
        return platform_window_.get();
    }

    const mirage_window_state& get_render_state() const {
        return *window_state_;
    }

private:
    mwindow* owner_;
    std::unique_ptr<platform_window> platform_window_;
    std::unique_ptr<mirage_window_state> window_state_;
    std::shared_ptr<mwidget> content_widget_;
    mirage_paint_context paint_context_;
    render_state render_state_;
    mouse_state mouse_;
};

