#pragma once
#include <SFML/Graphics.hpp>
#include <vector>
#include <iostream>
#include <random>
#include <ctime>

#define w_width 400
#define w_height 400
#define max_height 10

using namespace std;

typedef std::vector<std::vector<int> > Grid;

// global mt_rand seeding
mt19937 mt_rand(time(0));

/**
 * Drops a unit into the specific world at the specified position.
 *
 * If the position is out of bounds, then this function has no effect and the grid
 * is left unmodified.
 *
 * This may trigger a diffusion, which may propagate to other locations in the grid. A
 * cell diffuses when it reaches four units, and when it diffuses, it's emptied out
 * and a unit is dropped on each of the four neighbors.
 *
 * @param world The grid into which to drop the units.
 * @param row The row into which the unit is dropped.
 * @param col The column into which the unit is dropped.
 */
void dropUnit(Grid& world, int x, int y);

void randInit(Grid& world) {
	for (int i = 0; i < world.size(); ++i)
		for (int j = 0; j < world[0].size(); ++j)
			world[i][j] = mt_rand() % max_height;
}

bool isDone(Grid& world) {
	for (int i = 0; i < world.size(); ++i)
		for (int j = 0; j < world[0].size(); ++j)
			if (world[i][j] > 3) return false;
	return true;
}

void disperse4(Grid& world, int row, int col) {
	if (row > 0) ++world[row - 1][col];
	if (row < world.size() - 1) ++world[row + 1][col];
	if (col < world[row].size() - 1) ++world[row][col + 1];
	if (col > 0) ++world[row][col - 1];
}

void disperse(Grid& world) {
	for (int i = 0; i < world.size(); ++i)
		for (int j = 0; j < world[0].size(); ++j) {
			if (world[i][j] > 3) {
				world[i][j] -= 4;
				disperse4(world, i, j);
				/*if (i > 0) disperse4(world, i - 1, j);
				if (i < world.size() - 1) disperse4(world, i + 1, j);
				if (j < world[i].size() - 1) disperse4(world, i, j + 1);
				if (j > 0) disperse4(world, i, j - 1);*/
			}
		}

}

void dropUnit(Grid& world, int row, int col) {
	world[row][col] += 1;
	if (world[row][col] == 4) {
		world[row][col] = 0;
		if (row > 0) dropUnit(world, row - 1, col);
		if (row < world.size() - 1) dropUnit(world, row + 1, col);
		if (col < world[row].size() - 1) dropUnit(world, row, col + 1);
		if (col > 0) dropUnit(world, row, col - 1);
	}
}

void showWorld(vector<vector<int> > v) {
	for (int i = 0; i < v.size(); ++i) {
		for (int j = 0; j < v[i].size(); ++j)
			cout << v[i][j] << " ";
		cout << '\n';
	}
	cout << '\n';
}
