#ifndef CITY_GRID_H
#define CITY_GRID_H
#include <core/hash_map.h>
#include <modules/voxel/util/math/vector3i.h>
class TownGridData {
protected:
	struct shape_data {
		Ref<Shape> shape;
		Transform shape_xform;
	};
	struct cell_item {
		String name;
		AABB aabb;
		Transform xform;
		Dictionary data;
	};
	Vector<cell_item> items;
	HashMap<Vector3i, int, Vector3iHasher> grid;
	Vector3 origin;
	Vector3 scale;
public:
	void set_origin(const Vector3 &pos)
	{
		origin = pos;
	}
	void set_scale(const Vector3 &pos)
	{
		scale = pos;
	}
	Vector3i pos_to_grid(const Vector3 &pos)
	{
		Vector3i ret;
		ret.x = (int)(((pos.x - origin.x) / + scale.x * 0.5f) / scale.x);
		ret.y = (int)(((pos.y - origin.y) / + scale.y * 0.5f) / scale.y);
		ret.z = (int)(((pos.z - origin.z) / + scale.z * 0.5f) / scale.z);
		return ret;
	}
	Vector3 grid_to_pos(int x, int y, int z)
	{
		Vector3 ret;
		ret.x = (float)x * scale.x - scale.x * 0.5f + origin.x;
		ret.y = (float)y * scale.y - scale.y * 0.5f + origin.y;
		ret.z = (float)z * scale.z - scale.z * 0.5f + origin.z;
		return ret;
	}
	bool grid_can_place(const AABB &place, const Transform &xform)
	{
		Transform xform_inv = xform.affine_inverse();
		AABB xplace = xform.xform(place);
		int i, j, k, x1, y1, z1, x2, y2, z2;
		Vector3i a = pos_to_grid(xplace.position);
		Vector3i b = pos_to_grid(xplace.position + xplace.size);
		x1 = MIN(a.x, b.x);
		y1 = MIN(a.y, b.y);
		z1 = MIN(a.z, b.z);
		x2 = MAX(a.x, b.x);
		y2 = MAX(a.y, b.y);
		z2 = MAX(a.z, b.z);
		for (i = x1; i < x2; i++)
			for (j = y1; j < y2; j++)
				for (k = z1; k < z2; k++) {
					Vector3 key(i, j, k);
					Vector3 pos = grid_to_pos(i, j, k);
					Vector3 pos_inv = xform_inv.xform(pos);
					if (place.has_point(pos_inv) && grid.has(key))
						return false;
				}
		return true;
	}
	void grid_place(const StringName &name, const AABB &place, const Transform &xform)
	{
		int id = items.size();
		struct cell_item it;
		it.name = name;
		it.aabb = place;
		it.xform = xform;
		items.push_back(it);
		Transform xform_inv = xform.affine_inverse();
		AABB xplace = xform.xform(place);
		int i, j, k, x1, y1, z1, x2, y2, z2;
		Vector3i a = pos_to_grid(xplace.position);
		Vector3i b = pos_to_grid(xplace.position + xplace.size);
		x1 = MIN(a.x, b.x);
		y1 = MIN(a.y, b.y);
		z1 = MIN(a.z, b.z);
		x2 = MAX(a.x, b.x);
		y2 = MAX(a.y, b.y);
		z2 = MAX(a.z, b.z);
		for (i = x1; i < x2; i++)
			for (j = y1; j < y2; j++)
				for (k = z1; k < z2; k++) {
					Vector3 key(i, j, k);
					Vector3 pos = grid_to_pos(i, j, k);
					Vector3 pos_inv = xform_inv.xform(pos);
					if (place.has_point(pos_inv))
						grid[key] = id;
				}
	}
};
#endif
