#ifndef BATCH_GRID_H
#define BATCH_GRID_H

#include <vector>

#include "texture_atlas.h"

#include <GL/gl.h>

class karte_t;
class grund_t;
class ding_t;

struct pos_t {
	pos_t() {}
	pos_t(float x, float y, float z) : x(x), y(y), z(z) {}

	float x, y, z;
};

struct color_t {
	color_t() {}
	color_t(float r, float g, float b) : r(r), g(g), b(b) {}

	float r, g, b;
};

struct uv_t {
	uv_t() {}
	uv_t(float u, float v) : u(u), v(v) {}

	float u, v;
};

struct vertex_t {
	pos_t pos;
	color_t color;
	uv_t uv;

	vertex_t() {}
	vertex_t(const pos_t &pos, const color_t &color, const uv_t &uv) : pos(pos), color(color), uv(uv) {}
	vertex_t(float x, float y, float z, float r, float g, float b, float u = 0.0f, float v = 0.0f) : pos(x, y, z), color(r, g, b), uv(u, v) {}
};

struct batch_info_t {
	batch_info_t() : ground_primitives(0), underground_primitives(0) {}

	GLuint ground_primitives;
	GLuint underground_primitives;
};

class static_geometry {
public:
	static_geometry(karte_t *world);
	~static_geometry();

	void init_textures() {
		texture_atlas.init();
	}

	void reset();

	void set_dirty(int x, int y) {
		if (batches) {
			int i = x / batch_wh;
			int j = y / batch_wh;
			int index = j * grid_w + i;
			dirty[index] = true;
		}
	}

	void display();

private:
	karte_t *world;
	texture_atlas_t texture_atlas;

	int tile_height_step;

	int batch_wh;

	int grid_w, grid_h;

	GLuint *batches;
	batch_info_t *batch_infos;

	std::vector<bool> dirty;

	/**
	 * Used as a temporary working space.
	 */
	std::vector<vertex_t> work;

	/**
	 * Used as a temporary working space for underground geometry.
	 */
	std::vector<vertex_t> work_underground;

	void regenerate();
	void do_dirty();
	void recreate_batch(int i, int j);
	int add_tile(std::vector<vertex_t> *buffer, const grund_t *base);
	int add_static_object(std::vector<vertex_t> *buffer, const grund_t *base, const ding_t *object);
};

#endif // BATCH_GRID_H
