#pragma once

#include "Gallery_Session_Control.h"
#include "Gallery_Renderables.h"

#include <concepts>
#include <utility>

namespace renderive::web::gallery_adminive {

template <class Object, class Value, class Reader, class Writer>
auto callback_property(std::string name, std::string label,
                       adminive::Field_Control control, Reader reader, Writer writer) {
    auto accessor = structive::trusted_callable_accessor<Object>(
        std::move(reader), std::move(writer));
    static_assert(std::same_as<typename decltype(accessor)::value_type, Value>);
    return adminive::field(std::move(name), std::move(label), std::move(accessor))
        .editable()
        .unsynchronized()
        .control(control);
}

} // namespace renderive::web::gallery_adminive

namespace adminive {

template <>
struct Type_Descriptor<renderive::web::Gallery_Feedback_Policy> {
    static auto get() {
        using T = renderive::web::Gallery_Feedback_Policy;
        using namespace renderive::web::gallery_adminive;
        return adminive::object<T>("feedback_policy", "消费者反馈",
            boolean<&T::enabled>("enabled", "启用反馈"),
            boolean<&T::pixel>("pixel", "像素响应反馈"),
            boolean<&T::presentation>("presentation", "浏览器呈现反馈"),
            boolean<&T::manual>("manual", "手动反馈"),
            number<&T::manual_fps>("manual_fps", "手动反馈帧率"));
    }
};

template <class Scene_Type>
struct Type_Descriptor<renderive::web::Gallery_Session_Control<Scene_Type>> {
    static auto get() {
        using T = renderive::web::Gallery_Session_Control<Scene_Type>;
        using namespace renderive::web::gallery_adminive;
        const auto dirty = [](T& value) { value.scene_.notify_model_dirty(); };
        return adminive::object<T>("scene", "场景",
            callback_property<T, renderive::Color>(
                "background_color", "背景颜色", Field_Control::color,
                [](const T& value) { return value.scene_.background_color(); },
                [dirty](T& value, renderive::Color color) {
                    value.scene_.set_background_color(color);
                    dirty(value);
                }),
            callback_property<T, bool>(
                "performance_overlay", "性能叠加层", Field_Control::boolean,
                [](const T& value) {
                    const auto overlay = value.scene_.performance_overlay();
                    return overlay && overlay->enabled();
                },
                [dirty](T& value, bool enabled) {
                    renderive::set_performance_overlay_enabled(value.scene_, enabled);
                    dirty(value);
                }),
            callback_property<T, bool>(
                "renderable_visible", "显示渲染元素", Field_Control::boolean,
                [](const T& value) { return value.renderable_.is_visible(); },
                [dirty](T& value, bool visible) {
                    value.renderable_.set_visible(visible);
                    dirty(value);
                }),
            callback_property<T, renderive::Renderable_Cache_Mode>(
                "cache_mode", "缓存模式", Field_Control::select,
                [](const T& value) { return value.renderable_.get_cache_mode(); },
                [dirty](T& value, renderive::Renderable_Cache_Mode mode) {
                    value.renderable_.set_cache_mode(mode);
                    dirty(value);
                })
                .template enum_label<renderive::Renderable_Cache_Mode::Direct>("直接绘制")
                .template enum_label<renderive::Renderable_Cache_Mode::Local_Pixel>("本地像素缓存"),
            callback_property<T, std::string>(
                "object_name", "对象名称", Field_Control::text,
                [](const T& value) { return value.renderable_.object_name(); },
                [dirty](T& value, std::string name) {
                    value.renderable_.set_object_name(std::move(name));
                    dirty(value);
                }),
            callback_property<T, bool>(
                "frequency_limit_enabled", "启用帧率限制", Field_Control::boolean,
                [](const T& value) { return value.scene_.max_render_fps() > 0.0; },
                [dirty](T& value, bool enabled) {
                    if (enabled) {
                        if (value.scene_.max_render_fps() <= 0.0)
                            value.scene_.set_max_render_fps(30.0);
                    } else {
                        value.scene_.clear_max_render_fps();
                    }
                    dirty(value);
                }),
            callback_property<T, double>(
                "max_render_fps", "最大渲染帧率", Field_Control::number,
                [](const T& value) {
                    const double fps = value.scene_.max_render_fps();
                    return fps > 0.0 ? fps : 30.0;
                },
                [dirty](T& value, double fps) {
                    if (value.scene_.max_render_fps() > 0.0)
                        value.scene_.set_max_render_fps(fps);
                    dirty(value);
                }),
            callback_property<T, renderive::web::Gallery_Feedback_Policy>(
                "feedback", "消费者反馈", Field_Control::automatic,
                [](const T& value) { return value.feedback_; },
                [dirty](T& value, renderive::web::Gallery_Feedback_Policy feedback) {
                    value.feedback_ = std::move(feedback);
                    dirty(value);
                }));
    }
};


} // namespace adminive

namespace structive {

template <class Scene_Type>
struct Type_Descriptor<renderive::web::Gallery_Session_Control<Scene_Type>> {
    static auto get() {
        using T = renderive::web::Gallery_Session_Control<Scene_Type>;
        using renderive::web::gallery_action;
        return object<T>(type_metadata(
            gallery_action("reset", "恢复本图默认值", "Gallery_Scene::rebuild", "场景"),
            gallery_action("toggle_view", "切换 View 生命周期",
                           "Basic_Scene2D::activate_view / deactivate_view", "场景"),
            gallery_action("capture_next_frame", "Capture next frame",
                           "Scene_Base::capture_next_frame", "Performance Capture",
                           "Capture the next completed render frame", {}, {}, 0.0, true),
            gallery_action("capture_frames", "Capture N frames",
                           "Scene_Base::capture_frames", "Performance Capture",
                           "Capture consecutive completed render frames", "number",
                           "Frame count", 20.0, true),
            gallery_action("read_data_shape", "读取数据形状",
                           "Renderable data query / observer telemetry", "观察器")));
    }
};

} // namespace structive
