#include <psemek/ui/checkbox.hpp>
#include <psemek/ui/label.hpp>
#include <psemek/ui/image_view.hpp>

namespace psemek::ui
{

	label * checkbox::label() const
	{
		return dynamic_cast<struct label *>(child().get());
	}

	image_view * checkbox::icon() const
	{
		return dynamic_cast<struct image_view *>(child().get());
	}

	bool checkbox::on_event(mouse_move const & e)
	{
		bool const over = shape().contains(math::cast<float>(e.position));

		switch (state_) {
		case state_t::normal:
			if (over)
			{
				state_ = state_t::mouseover;
				on_state_changed(state_t::normal);
			}
			break;
		case state_t::mouseover:
		case state_t::mousedown:
			if (!over)
			{
				auto old = state_;
				state_ = state_t::normal;
				on_state_changed(old);
			}
			break;
		}

		return false;
	}

	bool checkbox::on_event(mouse_click const & e)
	{
		if (e.button != mouse_button::left) return false;

		switch (state_) {
		case state_t::normal:
			break;
		case state_t::mouseover:
			if (e.down)
			{
				state_ = state_t::mousedown;
				value_ = !value_;
				post_value_changed();
				on_state_changed(state_t::mouseover);
				return true;
			}
			break;
		case state_t::mousedown:
			if (!e.down)
			{
				state_ = state_t::mouseover;
				on_state_changed(state_t::mousedown);
				return true;
			}
			break;
		}

		return false;
	}

	void checkbox::set_value(bool value, bool signal)
	{
		value_ = value;
		if (signal)
			post_value_changed();
	}

	void checkbox::on_state_changed(state_t old)
	{
		if (state() == state_t::mousedown || old == state_t::mousedown)
		{
			post_reshape();
		}
	}

	void checkbox::post_value_changed()
	{
		if (callback_)
			post([cb = callback_, v = value_]{ cb(v); });
	}

}
