#include "game_planet_object.h"
#include "game_planet.h"
#include "gameframe.h"
#include "game_particle.h"


GamePlanetObject::GamePlanetObject(Vector2f _center, float _dist, float _baseAngle, ObjectType _type, GameFrame* _frame)
	: center(_center)
	, baseAngle(_baseAngle)
	, dist(_dist)
	, baseDist(_dist)
	, type(_type)
	, speed(0)
	, speedY(0)
	, cooldown(0)
	, shooting(0)
	, activationTime(0)
	, frame(_frame)
	, activity(1)
{
	angle = 3.14f;

	if (type >= Object_Collectible0_0 && type <= Object_Collectible3_4) {
		init(getCollectibleImage(type), Vector2f(0.5f, 0.9f), 10, 35, Collision::Collectible);
		setAnimationGroup(getCollectibleAnimation(type));
		setAnimationSequence("normal");
		layer = 1;
	}

	else if (type >= Object_Decoration0_0 && type <= Object_Decoration2_4) {
		int group = (type - Object_Decoration0_0) / 5;
		int which = (type - Object_Decoration0_0) % 5;
		init("enviro_"+String::IntegerToString(group)+"_"+String::IntegerToString(which)+".png", Vector2f(0.5f, 0.5f), 80, 25, Collision::Building);
		layer = -1;
	}

	else {

		switch (type) {
		case Object_Volcano: 
			init("volcano.png", Vector2f(0.5f, 0.9f), 10, 25, Collision::None);
			layer = 1;
			cooldown = (rand() % 1000) / 100.0f;
			break;
		case Object_Cloud0:
			init("cloud0.png", Vector2f(0.5f, 0.5f), 200 + rand()%80, 0, Collision::None);
			speed = (0.0005f + rand()%100/100000.0f) * 60;
			break;
		case Object_Building0:
			init("building0.png", Vector2f(0.5f, 0.5f), 80, 25, Collision::Building);
			layer = -1;
			break;
		case Object_Building1:
			init("building1.png", Vector2f(0.5f, 0.5f), 80, 25, Collision::Building);
			layer = -1;
			break;
		case Object_Building2:
			init("building2.png", Vector2f(0.5f, 0.5f), 80, 25, Collision::Building);
			layer = -1;
			break;
		case Object_Building3:
			init("building3.png", Vector2f(0.5f, 0.5f), 80, 25, Collision::Building);
			layer = -1;
			break;
		case Object_Rocket:
			init("RocketAnim9.png", Vector2f(0.5f, 0.1f), 0, 200, Collision::Rocket);
			setAnimationGroup("rocket");
			setAnimationSequence("flying");
			layer = 2;
			break;
		case Object_Particle:
			break;
		default:
			throw Exception("Unknown object type");
		}
	}

	//scale = 0.5f;
}

bool GamePlanetObject::step(float t, float at)
{
	elapsedTime = at;

	baseAngle += speed*t;
	dist += speedY*t;
	Angle1f a = Angle1f::FromRadians(angle);
	Vector2f p(0, dist);
	setPos(p.Rotate(a) + center);
	
	if (elapsedTime > activationTime) {
		if (cooldown > 0) {
			cooldown -= t;
		} else {
			if (type == Object_Volcano) {
				if (a.Distance(Angle1f::FromRadians(0)).GetRadians() < 1.0f) {
					playSound("Volcano"+String::IntegerToString(rand()%3)+".ogg");
				}
				cooldown = (((rand() % 1000) / 500.0f) + 7) / activity;
				shooting = 0.6f;
			}
		}

		if (shooting > 0) {
			shooting -= t;
		}

		if (a.Distance(Angle1f::FromRadians(0)).GetRadians() < 1.0f) {
			if (type == Object_Volcano) {
				int n = shooting > 0 ? 3 : 1;
				for (int i=0; i<n; i++) {
					float str = (shooting > 0 ? 1.0f/1.3f : 0.1f) * activity;
					Vector2f vel((rand()%101-50) / 1000.0f, (300 + (rand()%300) + (rand()%300))*str);
					spawnParticle(dist, baseAngle + (rand()%101-50) / 2000.0f, vel, 1.5f + (rand()%1000)/2000.0f, Particle_Lava);
				}
			}
		}
	}

	return true;
}

void GamePlanetObject::setAngle(float ang)
{
	angle = ang + baseAngle;
	Angle1f a = Angle1f::FromRadians(angle);
	Vector2f p(0, dist);
	setPos(p.Rotate(a) + center);
}

void GamePlanetObject::init(String name, Vector2f off, float distOff, float colRadius, Collision::Mask col)
{
	pivot = off;
	colType.mask = col;
	colType.radius = colRadius;
	texId = TextureManager::get(name)->GetId();
	dist += distOff;
}

void GamePlanetObject::setTimeLeft(float t, float stageTotal)
{
	// Cloud
	if (type == Object_Cloud0) {
		colour = Colour(1, 1, 1, min(1.0f, max(0.0f, sqrt((t-20.0f)/60.0f))));
	}
	
	// Rocket
	else if (type == Object_Rocket) {
		int n = 3;
		float shipTime = t < 0 ? (-2 - t) : (t - stageTotal - 2);
		float shipTime2 = t < 0 ? (-1 - t) : (t - stageTotal - 1);
		if (shipTime2 < 1) {
			if (t < 0) n = 1;
			else n = 2;
		}
		if (shipTime2 < 0) n = 0;

		String seq;
		if (n == 0) seq = "normal";
		if (n == 1) seq = "takeoff";
		if (n == 2) seq = "landing";
		if (n == 3) seq = "flying";
		if (anim->getSequence() != seq) {
			if (seq == "takeoff") playSound("spaceship_launch.ogg");
			if (seq == "landing") playSound("spaceship_land.ogg");
			setAnimationSequence(seq);
		}

		if (shipTime >= 0) {
			float off = pow(shipTime, 3.0f) * 40.0f;
			dist = baseDist + off;
		}
	}

	// Volcanoes
	else if (type == Object_Volcano) {
		activity = min(1.5f, max(1.0f, 2-t/stageTotal));
	}
}

void GamePlanetObject::spawnParticle(float dist, float baseAngle, Vector2f vel, float ttl, ParticleType type)
{
	spGamePlanetObject par(new GameParticle(center, dist, baseAngle, vel, ttl, type, frame));
	frame->planet->addObject(par);
}

Halley::String GamePlanetObject::getCollectibleImage(ObjectType type)
{
	return getCollectibleCode(type) + ".png";
}

Halley::String GamePlanetObject::getCollectibleAnimation(ObjectType type)
{
	return getCollectibleCode(type);
}

int GamePlanetObject::getCollectibleGroup( ObjectType type )
{
	int val = type - Object_Collectible0_0;
	return val / 5;
}


Halley::String GamePlanetObject::getCollectibleCode(ObjectType type)
{
	int val = type - Object_Collectible0_0;
	int group = val / 5;
	int n = val % 5;

	const char* groups[] = { "plant", "animal", "people", "rare" };

	return String("res_")+groups[group]+"_00"+String::IntegerToString(n);
}

void GamePlanetObject::render(Renderer& renderer) const
{
	if (elapsedTime > activationTime) {
		Sprite::render(renderer);
	}
}

Halley::String GamePlanetObject::getCollectibleName(ObjectType type)
{
	const char* names[] = {
		"Grass",
		"Corn",
		"Wheat",
		"Pumpkin",
		"Sunflower",
		"Chicken",
		"Bees",
		"Bear",
		"Dodo",
		"Flying Cow",
		"Chef",
		"Doctor",
		"Game Developer",
		"Goth",
		"Bowie",
		"Katamari",
		"Arcade",
		"Papa Bolota",
		"Jules",
		"Talbot" };
	return names[type - Object_Collectible0_0];
}
