#pragma once

#include <psemek/ui/element.hpp>
#include <psemek/ui/container.hpp>
#include <psemek/ui/box_shape.hpp>

#include <psemek/util/ndarray.hpp>

namespace psemek::ui
{

	struct grid_layout
		: container
	{
		children_range children() const override;

		virtual bool add_child(std::shared_ptr<element> c) override;
		virtual bool has_child(element * c) const override;
		virtual std::shared_ptr<element> remove_child(element * c) override;

		virtual std::size_t row_count() const { return children_.dim(0); }
		virtual std::size_t column_count() const { return children_.dim(1); }

		virtual void set_row_count(std::size_t count);
		virtual void set_column_count(std::size_t count);
		virtual void set_size(std::size_t rows, std::size_t columns);

		virtual void set_row_weight(std::size_t i, float w);
		virtual void set_column_weight(std::size_t i, float w);

		virtual std::shared_ptr<element> get(std::size_t i, std::size_t j) const;
		virtual std::shared_ptr<element> set(std::size_t i, std::size_t j, std::shared_ptr<element> c);
		virtual std::shared_ptr<element> remove(std::size_t i, std::size_t j);

		virtual void add_row();
		virtual void add_row(std::shared_ptr<element> c);
		virtual void add_column();
		virtual void add_column(std::shared_ptr<element> c);

		virtual void set_outer_margin(bool value);
		virtual bool outer_margin() const { return outer_margin_; }

		math::box<float, 2> size_constraints() const override;

		math::interval<float> width_constraints(float height) const override;

		math::interval<float> height_constraints(float width) const override;

		struct shape const & shape() const override { return shape_; }
		void reshape(math::box<float, 2> const & bbox) override;

		bool transparent() const override { return !hint(); }

		void draw(painter &) const override {}

		~grid_layout() override;

	protected:
		std::vector<math::interval<float>> row_shape_;
		std::vector<math::interval<float>> column_shape_;

	private:
		util::ndarray<std::shared_ptr<element>, 2> children_;
		std::vector<element *> children_range_;

		std::vector<float> row_weight_;
		std::vector<float> column_weight_;

		bool outer_margin_ = true;

		box_shape shape_;
	};

}
