#pragma once
#include <memory>

#include "mpanel_widget.h"
#include "mwidget.h"
#include "widget_new.h"
#include "compound_widget/mbutton.h"

/**
 * @struct mwidget_decl
 * @tparam WidgetType 要创建的组件类型
 * @brief 组件布局声明结构体, 用于创建和管理组件实例
 */
template<typename WidgetType>
struct mwidget_decl {
	using construct_args = typename WidgetType::construct_args;
    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)...);
    }

	// 禁止复制
	mwidget_decl(const mwidget_decl&) = delete;
	mwidget_decl& operator=(const mwidget_decl&) = delete;

	template<typename ...Args>
	auto operator[](Args&&... in_args) {
		return std::static_pointer_cast<WidgetType>((*widget_)[std::forward<Args>(in_args)...]);
	}
	auto& setup(const construct_args& in_args) {
		widget_->setup_widget(in_args);
		return *this;
	}

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

/**
 * @brief 创建一个新的组件插槽
 * @param type 组件类型
 * @code
// 创建一个组件插槽
mslot(mv_box)
// 使用方式如下
auto button = std::make_shared<mbutton>();
button->push_slot(
	mslot(mbutton)
	.margin({10})
	.visibility(visibility_t::visible)
	(text_block)
);
 * @endcode
 */
#define mslot(type) type::slot_type()

#define margs(type) type::construct_args()

/**
 * @param type 组件类型
 * @code
// 创建一个新的组件实例
mnew(mv_box)
[
	// 第一个子组件
	mslot(mv_box)
	.h_alignment(horizontal_alignment_t::center)
	.v_alignment(vertical_alignment_t::center)
	(child_widget),

	// 第二个子组件
	mslot(mv_box)
	(child_widget2)
];
 * @endcode
 * @note 对于简单的创建控件也可以不使用mnew方式，而是使用std::make_shared<type>()，然后使用布局容器的成员函数来管理布局，具体可以看mcompound_widget和mpanel_widget
 */
#define mnew(type, ...) mwidget_decl<type>().setup(type::construct_args()__VA_ARGS__)
