#pragma once

#include <psemek/util/updater.hpp>

#include <cmath>

namespace psemek::util
{

	template <typename Time, typename Value = Time>
	struct smooth_updater
		: updater<Time>
	{
		smooth_updater(Value & value, Time speed)
			: value_(value)
			, target_(value)
			, speed_(speed)
		{}

		template <typename H>
		smooth_updater & operator = (H new_value)
		{
			target_ = new_value;
			return *this;
		}

		template <typename H>
		smooth_updater & operator += (H new_value)
		{
			target_ += new_value;
			return *this;
		}

		template <typename H>
		smooth_updater & operator -= (H new_value)
		{
			target_ -= new_value;
			return *this;
		}

		template <typename H>
		smooth_updater & operator *= (H new_value)
		{
			target_ *= new_value;
			return *this;
		}

		template <typename H>
		smooth_updater & operator /= (H new_value)
		{
			target_ /= new_value;
			return *this;
		}

		void update(Time dt) override
		{
			using std::lerp;
			value_ = lerp(target_, value_, std::exp(- dt * speed_));
		}

		Value const & value() const
		{
			return target_;
		}

	private:
		Value & value_;
		Value target_;
		Time speed_;
	};

}
