#pragma once

#include <psemek/math/vector.hpp>
#include <psemek/math/point.hpp>
#include <psemek/math/matrix.hpp>
#include <psemek/math/affine_transform.hpp>
#include <psemek/gfx/color.hpp>
#include <psemek/util/pimpl.hpp>

#include <memory>

namespace psemek::gfx
{

	struct painter2
	{
		painter2();
		~painter2();

		using transform_type = math::affine_transform<float, 2, 2>;

		struct fill_style
		{
			gfx::color_rgba color;
		};

		struct stroke_style
		{
			gfx::color_rgba color;
			float width;
		};

		struct frame_builder
		{
			// Matrix stack (NB: default transform is OpenGL standart [-1..1]^2)
			virtual void push_matrix(transform_type const & matrix) = 0;
			virtual void pop_matrix() = 0;
			virtual void reset_matrix() = 0;

			// Fill primitives
			virtual void fill_circle(math::point<float, 2> const & center, float radius, fill_style const & style) = 0;
			virtual void fill_ellipse(math::point<float, 2> const & center, math::vector<float, 2> const & radii, float rotation, fill_style const & style) = 0;
			virtual void fill_square(math::point<float, 2> const & center, float extent, float rotation, fill_style const & style) = 0;
			virtual void fill_rectangle(math::point<float, 2> const & center, math::vector<float, 2> const & extent, float rotation, fill_style const & style) = 0;

			// Stroke primitives
			virtual void stroke_circle(math::point<float, 2> const & center, float radius, stroke_style const & style) = 0;
			virtual void stroke_ellipse(math::point<float, 2> const & center, math::vector<float, 2> const & radii, float rotation, stroke_style const & style) = 0;
			virtual void stroke_square(math::point<float, 2> const & center, float extent, float rotation, stroke_style const & style) = 0;
			virtual void stroke_rectangle(math::point<float, 2> const & center, math::vector<float, 2> const & extent, float rotation, stroke_style const & style) = 0;

			// Render everything on screen (called automatically in destructor)
			virtual void flush() = 0;

			virtual ~frame_builder() {}
		};

		std::unique_ptr<frame_builder> begin_frame(math::vector<int, 2> viewport_size);

	private:
		psemek_declare_pimpl
	};

}
