//////////////////////////////////////////////////////////////////////////
//
// This file is part of the BWEM Library.
// BWEM is free software, licensed under the MIT/X11 License. 
// A copy of the license is provided with the library in the LICENSE file.
// Copyright (c) 2015, 2016, Igor Dimitrijevic
//
//////////////////////////////////////////////////////////////////////////


#ifndef BWEM_GRID_MAP_H
#define BWEM_GRID_MAP_H

#include <BWAPI.h>
#include <vector>
#include "map.h"
//#include "tiles.h"
//#include "area.h"
#include "utils.h"
#include "defs.h"


namespace BWEM
{

class Tile;
class MiniTile;
class Area;
class Mineral;
class Geyser;
class StaticBuilding;
class ChokePoint;
class Map;


//////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                          //
//                                  class GridMap
//                                                                                          //
//////////////////////////////////////////////////////////////////////////////////////////////
//

template<class T, int N>
class GridMap
{
public:
	typedef T Cell;
	enum {cell_width_in_tiles = N};
	enum {tiles_per_cell = cell_width_in_tiles};

								GridMap(Map * pMap);

	int							Width() const						{ return m_width; }
	int							Height() const						{ return m_height; }

	const Cell &				GetCell(int i, int j, bool noCheck = false) const	{ bwem_assert(noCheck || ValidCoords(i, j)); return m_Cells[m_width * j + i]; }
	Cell &						GetCell(int i, int j, bool noCheck = false)			{ bwem_assert(noCheck || ValidCoords(i, j)); return m_Cells[m_width * j + i]; }

	const Cell &				GetCell(const BWAPI::TilePosition & p, bool noCheck = false) const	{ bwem_assert(noCheck || m_pMap->Valid(p)); return GetCell(p.x/N, p.y/N, no_check); }
	Cell &						GetCell(const BWAPI::TilePosition & p, bool noCheck = false)		{ bwem_assert(noCheck || m_pMap->Valid(p)); return GetCell(p.x/N, p.y/N, no_check); }
	std::pair<int, int>			GetCellCoords(const BWAPI::TilePosition & p, bool noCheck = false) const	{ bwem_assert(noCheck || m_pMap->Valid(p)); return make_pair(p.x/N, p.y/N); }
	BWAPI::TilePosition			GetTopLeft(int i, int j, bool noCheck = false) const				{ bwem_assert(noCheck || ValidCoords(i, j)); return BWAPI::TilePosition(i*N, j*N); }
	BWAPI::TilePosition			GetBottomRight(int i, int j, bool noCheck = false) const			{ bwem_assert(noCheck || ValidCoords(i, j)); return BWAPI::TilePosition((i+1)*N, (j+1)*N) - 1; }
	BWAPI::TilePosition			GetCenter(int i, int j, bool noCheck = false) const					{ bwem_assert(noCheck || ValidCoords(i, j)); return BWAPI::TilePosition(i*N, j*N) + N/2; }

	const std::vector<Cell> &	Cells() const						{ return m_Cells; }

	bool						ValidCoords(int i, int j) const		{ return (0 <= i) && (i < Width()) && (0 <= j) && (j < Height()); }

private:
	Map *						m_pMap;

	int							m_width;
	int							m_height;
	std::vector<Cell>			m_Cells;
};


template<class T, int N>
GridMap<T, N>::GridMap(Map * pMap)
: m_pMap(pMap),
	m_width(pMap->Size().x / N),
	m_height(pMap->Size().y / N),
	m_Cells(m_width * m_height)
{
	static_assert(N > 0, "GridMap::cell_width_in_tiles must be > 0");
	bwem_assert_throw(N <= min(pMap->Size().x, pMap->Size().y));
	bwem_assert_throw(pMap->Size().x % N == 0);
	bwem_assert_throw(pMap->Size().y % N == 0);


}


} // namespace BWEM


#endif

