#include <psemek/app/application_base.hpp>
#include <psemek/app/default_application_factory.hpp>
#include <psemek/gfx/painter2.hpp>
#include <psemek/gfx/gl.hpp>
#include <psemek/math/orthographic.hpp>
#include <psemek/math/translation.hpp>
#include <psemek/math/shear.hpp>
#include <psemek/random/generator.hpp>
#include <psemek/random/uniform.hpp>
#include <psemek/util/clock.hpp>

using namespace psemek;

struct painter_app
	: app::application_base
{
	painter_app(options const &, context const &)
	{}

	void update() override
	{
		[[maybe_unused]] float const dt = frame_clock_.restart().count();

		angle_ += dt;
	}

	void present() override
	{
		gl::Viewport(0, 0, state().size[0], state().size[1]);

		gl::ClearColor(1.f, 1.f, 1.f, 1.f);
		gl::Clear(gl::COLOR_BUFFER_BIT);

		math::box<float, 2> view_box{{{0.f, state().size[0]}, {state().size[1], 0.f}}};

		auto builder = painter_.begin_frame(state().size);
		builder->push_matrix(math::orthographic<float, 2>(view_box).transform());
		builder->fill_circle({200.f, 200.f}, 100.f, {.color = {0, 0, 255, 255}});
		builder->push_matrix(math::translation<float, 2>({200.f, 600.f}).transform());
		builder->push_matrix(math::shear<float, 2>(0, 1, 1.f).transform());
		builder->stroke_square({0.f, 0.f}, 100.f, math::rad(45.f), {.color = {255, 127, 255, 255}, .width = 25.f});
		builder->pop_matrix();
		builder->pop_matrix();
		builder->stroke_ellipse({400.f, 400.f}, {50.f, 5.f}, angle_, {.color = {255, 0, 0, 255}, .width = 2.f});
		builder->stroke_ellipse({960.f, 540.f}, {400.f, 20.f}, angle_ * 0.1f, {.color = {255, 0, 0, 255}, .width = 20.f});
		builder->flush();
	}

private:
	random::generator rng_;

	util::clock<> frame_clock_;

	float angle_ = 0.f;

	gfx::painter2 painter_;
};

namespace psemek::app
{

	std::unique_ptr<application::factory> make_application_factory()
	{
		return default_application_factory<painter_app>({.name = "Painter example", .multisampling = 0});
	}

}
