const EventEmitter = require('events');

const Grid = require('../../../gamelib/grid/Grid.js');
const BaseCell = require('../../../gamelib/grid/BaseCell.js');

const Wall = require('./Wall.js');
const Mouse = require('./Mouse.js');
const Cat = require('./Cat.js');
const House = require('./House.js');
const Trap = require('./Trap.js');

const LAYER_V_WALL = 2;
const LAYER_H_WALL = 1;

class Game extends EventEmitter {
	static 
() {
		return new this();
	}
	constructor() {
		super();
		this.board = Grid.create({
			rows: 12,
			cols: 9,
			layerCount: 3
		});
	}
	load(data) {
		this.data = data;
		this.cats = [];
		this.mouses = [];
		data.wall.forEach(p => this.addWall(p[0], p[1], p[2]));
		data.mouse.forEach(p => this.addMouse(p[0], p[1], p[2]));
		data.cat.forEach(p => this.addCat(p[0], p[1], p[2]));
	}
	start() {
		this.runningMouse = this.mouses.length;
		this.mouses.forEach((item) => {
			item.state = 'run';
		});
		this.cats.forEach((item) => {
			item.state = 'run';
		});
	}
	reset() {
		this.emit('reset');
		this.load(this.data);
	}
	win() {
		this.emit('win');
	}
	lost() {
		this.emit('lost');
	}
	addWall(i, j, dir) {
		var layer = (dir === 0) ? LAYER_H_WALL : LAYER_V_WALL;
		var wall = this.board.createCell({
			i, j, dir, layer
		}, BaseCell);
		this.emit('addWall', wall);
		return wall;
	}
	removeWall(i, j, dir) {
		if (dir === 0) {
			layer = LAYER_H_WALL;
		} else {
			layer = LAYER_V_WALL;
		}
		var cell = this.board.layers[layer][i][j];
		if (cell) {
			cell.destroy();
			this.board.destroyCell(cell);
		}
	}
	addHouse(i, j) {
		var house = this.board.createCell({
			i, j, dir, layer: 0
		}, House);
		this.emit('addHouse', house);
		return house;
	}
	removeHouse(i, j) {
		var house = this.board.layers[0][i][j];
		if (house) {
			this.board.destroyCell(house);
		}
	}
	addTrap(i, j) {
		var trap = this.board.createCell({
			i, j, dir, layer: 0
		}, Trap);
		this.emit('addTrap', trap);
		return trap;
	}
	removeTrap(i, j) {
		var trap = this.board.layers[0][i][j];
		if (trap) {
			this.board.destroyCell(trap);
		}
	}
	addCat(i, j, dir) {
		var cat = Cat.create(this, {
			i, j, dir
		});
		this.cats.push(cat);
		this.emit('addCat', cat);
		return cat;
	}
	removeCat(cat) {
		cat.destroy();
		var p = this.cats.indexOf(cat);
		if (p >= 0) {
			this.cats.splice(p, 1);
		}
	}
	addMouse(i, j, dir) {
		var mouse = Mouse.create(this, {
			i, j, dir
		});
		this.mouses.push(mouse);
		this.emit('addMouse', mouse);
		return mouse;
	}
	removeMouse(mouse) {
		mouse.destroy();
		var p = this.mouses.indexOf(mouse);
		if (p >= 0) {
			this.mouses.splice(p, 1);
		}
	}
	isWall(i, j, dir) {
		if (dir === 0) {
			if (j <= 0) {
				return true;
			} else {
				return !!this.board.layers[LAYER_V_WALL][i][j - 1];
			}
		} else if (dir === 1) {
			if (i >= this.board.rows - 1) {
				return true;
			} else {
				return !!this.board.layers[LAYER_H_WALL][i][j];
			}
		} else if (dir === 2) {
			if (j >= this.board.cols - 1) {
				return true;
			} else {
				return !!this.board.layers[LAYER_V_WALL][i][j];
			}
		} else if (dir === 3) {
			if (i <= 0) {
				return true;
			} else {
				return !!this.board.layers[LAYER_H_WALL][i - 1][j];
			}
		}
		return true;
	}
	test(cat, mouse) {
		var dx = cat.x - mouse.x;
		var dy = cat.y - mouse.y;
		var dist = Math.sqrt(dx * dx + dy * dy);
		return dist < 0.1;
	}
	update(dt) {
		//this.board.update(dt);
		this.mouses.forEach(item => item.update(dt));
		this.cats.forEach(item => item.update(dt));
	}
}

module.exports = Game;
create