#pragma once

#include <psemek/ui/element.hpp>

#include <functional>

namespace psemek::ui
{

	struct slider
		: element
	{
		bool on_event(mouse_move const & e) override;
		bool on_event(mouse_click const & e) override;
		bool on_event(mouse_wheel const & e) override;

		virtual math::interval<int> value_range() const { return value_range_; }
		virtual void set_value_range(math::interval<int> i, bool notify = true);

		virtual int value() const { return value_; }
		virtual void set_value(int v, bool notify = true);

		virtual bool cyclic() const { return cyclic_; }
		virtual void set_cyclic(bool cyclic) { cyclic_ = cyclic; }

		using on_value_changed_callback = std::function<void(int)>;

		void on_value_changed(on_value_changed_callback callback, bool notify = true);

	protected:
		enum class state_t
		{
			normal,
			mouseover,
			mousedown,
		};

		virtual state_t state() const { return state_; }

		virtual void on_state_changed(state_t /* old */) {}

		virtual math::interval<float> slider_range() const;

	private:
		math::interval<int> value_range_{0, 100};
		int value_ = 0;

		bool cyclic_ = false;

		state_t state_ = state_t::normal;
		std::optional<math::point<int, 2>> mouse_;
		std::optional<math::interval<float>> drag_range_;

		on_value_changed_callback callback_;

		void post_value_changed();

		int compute_value(int x) const;
		int compute_value(int x, math::interval<float> const & range) const;
	};

}
