//
//  DungeonGame.cpp
//  GlobalGameJam15
//
//  Created by Cesar Parent on 23/01/2015.
//  Copyright (c) 2015 Cesar Parent. All rights reserved.
//

#include "DungeonGame.h"
#include "Defines.h"
#include "MainCharacter.h"
#include "Enemy.h"
#include "MapLayer.h"
#include "PauseMenu.h"
#include "TimedLabel.h"
#include "FailMenu.h"
#include "IntroMenu.h"
#include "Chest.h"
#include "SuccessScreen.h"

DungeonGame::DungeonGame(Game& game) : Scene(game, kGameWidth/2, kGameHeight/2)
{
	setAnchorPoint(0, 0);
	setPosition(0, 0);
	setXScale(2);
	setYScale(2);
	
	_player = new MainCharacter();
	_gameLayer = new MapLayer(game, _player);
	_player->setMoveController(this);
	
	_chest = new Chest();
	
	_gameLayer->addChild(_chest);
	_gameLayer->addChild(_player);
	_gameLayer->setAnchorPoint(0, 0);
	_gameLayer->setPosition(0, 0);
	addChild(_gameLayer);
	
	_pauseMenu = new PauseMenu(game);
	_failMenu = new FailMenu(game);
	_successMenu = new SuccessScreen(game);
	
	_spawnPlayer();
	_spawnEnemies();
	_spawnChest();
	_currentTurn = kAITurn;
	nextTurn();
	
	_gameLayer->collideChildren(true);
	
	addChild(new IntroMenu(game));
}

DungeonGame::~DungeonGame()
{
	for(auto enemy: _enemies)
	{
		delete enemy;
	}
	delete _chest;
	delete _player;
	delete _gameLayer;
	delete _pauseMenu;
	delete _successMenu;
}

void DungeonGame::finishedIntro()
{
	Controls::setDelegate(this);
}

void DungeonGame::update(int timeInterval)
{
	Scene::update(timeInterval);
	if(_enemyMoves <= 0 && _currentTurn == kAITurn)
	{
		Point<int> playerTile = _player->tile();
		if(enemyOnTile(playerTile.x, playerTile.y))
		{
			Sound::playSound("assets/sounds/caught.wav");
			addChild(_failMenu);
		}
		nextTurn();
	}
	_gameLayer->setX(-(_player->position.x - (kGameWidth/4)));
	_gameLayer->setY(-(_player->position.y - (kGameHeight/4)));
}

void DungeonGame::didCollide(Collision collision)
{
	addChild(_successMenu);
}

#pragma mark turn handling code

void DungeonGame::nextTurn()
{
	_currentTurn = (_currentTurn == kAITurn) ? kPlayerTurn : kAITurn;
	
	switch (_currentTurn) {
		case kAITurn:
			takeTurn();
			break;
			
		case kPlayerTurn:
			((MainCharacter*)_player)->takeTurn();
			break;
	}
}

void DungeonGame::takeTurn()
{
	_enemyMoves = (int)_enemies.size();
	Sound::playSound("assets/sounds/jump.wav");
	for(auto e: _enemies)
	{
		((Enemy*)e)->aiMove();
	}
}


#pragma mark spawning code

void DungeonGame::_spawnPlayer()
{
	bool validLocation = false;
	Point<int> spawnPoint = Point<int>(0, 0);
	do
	{
		spawnPoint.x = rand()%kMapWidth;
		spawnPoint.y = rand()%kMapHeight;
		validLocation = _gameLayer->moveAllowed(spawnPoint);
		
	} while(!validLocation);
	_player->setTile(spawnPoint.x, spawnPoint.y);
}

void DungeonGame::_spawnChest()
{
	bool validLocation = false;
	Point<int> spawnPoint = Point<int>(0, 0);
	float distance;
	int neighbours;
	
	do
	{
		spawnPoint.x = rand()%kMapWidth;
		spawnPoint.y = rand()%kMapHeight;
		neighbours = _gameLayer->aliveNeighbours(spawnPoint.x, spawnPoint.y);
		distance = _gameLayer->distanceToPlayer((spawnPoint.x+0.5)*kTileSize,
												(spawnPoint.y+0.5)*kTileSize);
		validLocation = (_gameLayer->moveAllowed(spawnPoint) &&
						 distance > kChestDistance*kTileSize);
	} while(!validLocation);
	_chest->setTile(spawnPoint.x, spawnPoint.y);
}

void DungeonGame::_spawnEnemies()
{
	bool validLocation = false;
	Point<int> spawnPoint = Point<int>(0, 0);
	float distance;
	
	for(int i = 0; i < kNumEnemies; ++i)
	{
		Enemy* guard = new Enemy();
		do
		{
			spawnPoint.x = rand()%kMapWidth;
			spawnPoint.y = rand()%kMapHeight;
			distance = _gameLayer->distanceToPlayer((spawnPoint.x+0.5)*kTileSize,
													(spawnPoint.y+0.5)*kTileSize);
			validLocation = (_gameLayer->moveAllowed(spawnPoint) &&
							 distance > kVisionRadius*kTileSize);
			
		} while(!validLocation);
		guard->setTile(spawnPoint.x, spawnPoint.y);
		guard->setMoveController(this);
		_enemies.push_back(guard);
		_gameLayer->addChild(guard);
	}
}

bool DungeonGame::enemyOnTile(int x, int y)
{
	Point<int> enemyTile, enemyTarget;
	for(auto enemy: _enemies)
	{
		enemyTile = enemy->tile();
		enemyTarget = enemy->targetTile();
		if((enemyTile.x == x && enemyTile.y == y) ||
		   (enemyTarget.x == x && enemyTarget.y == y)) return true;
	}
	return false;
}

#pragma mark delegates

void DungeonGame::didEnterStack()
{
	//Controls::setDelegate(this);
}

void DungeonGame::didLeaveStack()
{
	Controls::setDelegate(nullptr);
	delete this;
}

void DungeonGame::controllerButtonPressBegan(int controller, SDL_GameControllerButton button)
{
	switch (button) {
		case SDL_CONTROLLER_BUTTON_START:
			addChild(_pauseMenu);
			break;
			
		case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
			_player->move(kMotionDown);
			break;
			
		case SDL_CONTROLLER_BUTTON_DPAD_UP:
			_player->move(kMotionUp);
			break;
			
		case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
			_player->move(kMotionLeft);
			break;
			
		case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
			_player->move(kMotionRight);
			break;
			
		default:
			break;
	}
}


void DungeonGame::keyboardPressBegan(SDL_Scancode key)
{
	switch (key) {
		case SDL_SCANCODE_UP:
			_player->move(kMotionUp);
			break;
		case SDL_SCANCODE_DOWN:
			_player->move(kMotionDown);
			break;
		case SDL_SCANCODE_LEFT:
			_player->move(kMotionLeft);
			break;
		case SDL_SCANCODE_RIGHT:
			_player->move(kMotionRight);
			break;
		case SDL_SCANCODE_ESCAPE:
			addChild(_pauseMenu);
			break;
		default:
			break;
	}
	if(key == SDL_SCANCODE_F)
	{
		_game.toggleFullScreen();
	}
}