#pragma once
#include <memory>

#include "mpanel_widget.h"
#include "mwidget.h"

// 前向声明
template<typename WidgetType>
struct mwidget_decl;

template<typename T>
concept has_add_slot = requires(T& t) {
    { t.add_slot() };
};

template<typename T>
concept has_set_content = requires(T& t, std::shared_ptr<mwidget> in_widget) {
    t.set_content(in_widget);
};

template<typename WidgetType>
struct mwidget_decl {
    mwidget_decl() {
        widget_ = std::make_shared<WidgetType>();
    }

    template<typename... Args>
    explicit mwidget_decl(Args&&... in_args) {
        widget_ = std::make_shared<WidgetType>(std::forward<Args>(in_args)...);
    }

    auto& operator[](const std::shared_ptr<mwidget>& in_widget) requires has_set_content<WidgetType> {
        return widget_->set_content(in_widget);
    }

	auto& operator+(const typename WidgetType::slot_type& in_slot) requires has_add_slot<WidgetType> {
		widget_->push_slot(in_slot);
		return *this;
	}

	auto& s() requires has_add_slot<WidgetType> {
	    return widget_->add_slot();
    }

    operator std::shared_ptr<mwidget>() const { return widget_; }
    std::shared_ptr<WidgetType> widget_;
};

#define mnew(type, ...) mwidget_decl<type>(__VA_ARGS__)
#define mslot(type) +type::slot_type()
