#include "gameplayer.h"	
#include "gameframe.h"
#include "game_planet.h"
#include "game_stats.h"
#include "types.h"

GamePlayer::GamePlayer(spInputBase in, Vector2f _pos, GamePlanet* _planet)
	: input(in)
	, jumping(0)
	, planet(_planet)
	, aSpeed(0)
	, facing(1)
	, posX(0)
	, dashing(0)
	, spawning(30)
	, dying(0)
	, jumpRequest(0)
	, jumpRecovery(0)
	, active(true)
	, gotEndTime(false)
	, neutralY(true)
	, autoPilot(false)
	, invulnerable(120)
	, stepN(0)
{
	layer = 10;

	pos = _pos;
	basePos = pos;

	//texId = TextureManager::get("player0.png")->GetId();
	setAnimationGroup("player");
	setAnimationSequence("normal");

	colType.mask = Collision::Player;
	colType.radius = 10;

	addTrigger(Collision::Deadly, [this] (Sprite& s) {
		die();
	});

	addTrigger(Collision::Collectible, [this] (Sprite& s) {
		collect((GamePlanetObject&)s);
	});

	addTrigger(Collision::Rocket, [this] (Sprite& s) {
		onTouchRocket();
	});
}

void GamePlayer::stepJump(float t, float at)
{
	// Jumping sequence
	if (jumpRequest > 0) jumpRequest--;
	if (!autoPilot && active && input->isButtonPressed(Player_Action1)) {
		jumpRequest = 5;	// Jump tolerance
	}
	if (jumping == 0) {
		if (jumpRequest > 0) {
			playSound("Jump"+String::IntegerToString(rand()%3)+".ogg");
			vel += Vector2f(0, 180);
			jumping++;
		}
	} else {
		if (active && input->isButtonDown(Player_Action1)) {
			if (jumping < 18) {
				int v = 30;
				if (jumping >= 10) v -= (jumping-10)*3;
				vel += Vector2f(0, v);
				jumping++;
			}
		} else {
			jumping = 999;
		}
		vel -= Vector2f(0, 20);	// Gravity
	}
}

void GamePlayer::stepMovement(float t, float at)
{
	float maxSpeed = 0.5f;	// Normal speed
	if (autoPilot) maxSpeed *= 0.70f;
	if (!active) maxSpeed = 0;

	if (inventory.size() > 1) {
		maxSpeed *= 0.5f;
	}

	float ix = active ? (autoPilot ? 1 : input->getAxis(0)) : 0;
	float a;

	if (active && jumping == 0 && !planet->isSafe()) die();

	if (dashing == 0) {
		a = 0.05f;
		if (ix != 0) facing = ix > 0 ? 1 : -1;

		if (jumping == 0) {
			if (jumpRecovery > 0) setAnimationSequence("jumpRecovery");
			else {
				if (fabs(ix) > 0.01f) {
					setAnimationSequence("walking");
					int f = anim->getFrame();
					if (f != lastFrame) {
						lastFrame = f;
						if (f == 0 || f == 3) playSound("step"+String::IntegerToString(1+(rand()%6))+".ogg");
					}
				}
				else setAnimationSequence("normal");
			}
		} else {
			if (vel.y > 0) setAnimationSequence("jumping");
			else setAnimationSequence("falling");
		}

		if (!autoPilot && active && input->isButtonPressed(Player_Action2)) {
			playSound("dash.ogg");
			int n = 25;	// Dash length in frames
			dashing = facing * n;
		}
	} else {
		setAnimationSequence("hover");
		a = 0.2f;
		facing = dashing / abs(dashing);
		dashing -= facing;
		ix = facing;
		maxSpeed *= 3; // Dash increase
	}

	flip = facing == -1;

	float tSpeed = ix * maxSpeed;
	aSpeed = aSpeed * (1-a) + tSpeed * a;

	posX += aSpeed * t;
	planet->setAngle(posX);
}

bool GamePlayer::step(float t, float at)
{
	stepN++;
	if (!active) return false;

	if (rocket > 0) rocket--;
	if (jumpRecovery > 0) jumpRecovery--;

	if (fabs(input->getAxis(1)) < 0.1f) neutralY = true;

	if (dying) {
		setAnimationSequence("explosion");
		if (dying > 1) dying--;

		pos.y += float(dying) / 6.0f - 2.0f;
	}

	else {
		if (spawning) {
			spawning--;
			planet->setAngle(posX, 0.1f);
		}

		else {
			if (invulnerable > 0) invulnerable--;
			stepJump(t, at);
			stepMovement(t, at);

			// Drop items
			if (!autoPilot && neutralY && input->getAxis(1) > 0.9) {
				neutralY = false;
				if (inventory.size() > 0 && jumping == 0) {
					playSound("droplootground.ogg");
					ObjectType type = inventory[0];
					planet->createObject(-planet->getAngle(), type);
					inventory.erase(inventory.begin());
				}
			}
		}

		pos += vel * t;
		if (pos.y < basePos.y) {
			pos.y = basePos.y;
			vel.y = 0;
			if (jumping > 0) {
				// Touchdown
				playSound("contact.ogg");
				jumping = 0;
				jumpRecovery = 10;
			}
		}
	}

	return true;
}

void GamePlayer::die()
{
	if (active && !invulnerable) {
		if (dying == 0 && spawning == 0) {
			playSound("deathboom.ogg");
			playSound("dvoice"+String::IntegerToString(rand()%4)+".ogg");
			dying = 60;
		}
	}
}

void GamePlayer::render(Renderer& renderer) const
{
	if (active) {
		if (!spawning) {
			if (!invulnerable || (stepN / 10)%2 == 0)
			Sprite::render(renderer);
		}
	}
}

void GamePlayer::collect(GamePlanetObject& object)
{
	if (!autoPilot && inventory.size() < 2) {
		if (neutralY && input->getAxis(1) < -0.9) {
			if (object.isActive()) {
				playSound("gotitem.ogg");
				neutralY = false;
				ObjectType type = object.getType();
				int group = GamePlanetObject::getCollectibleGroup(type);
				if (group == 0) playSound("gotplant.ogg");
				if (group == 1) playSound("gotanimal.ogg");
				if (group == 2) playSound("gotpeople.ogg");
				inventory.push_back(type);
				object.setAlive(false);
			}
		}
	}
}

void GamePlayer::onTouchRocket()
{
	if (inventory.size() > 0) {
		playSound("droploot.ogg");
		for (size_t i=0; i<inventory.size(); i++) {
			GameStats::collected.push_back(inventory[i]);
		}
		inventory.clear();
	}
	rocket = 3;
}

void GamePlayer::endTime()
{
	if (!gotEndTime) {
		gotEndTime = true;
		if (rocket > 0) {
			active = false;
		} else {
			die();
		}
	}
}

void GamePlayer::setAutoPilot()
{
	autoPilot = true;
}
