#include "sprite.h"
#include "frame.h"
#include "renderer.h"
#include "audio.h"
#include "exception.h"
#include "animation.h"


using namespace Halley;


Sprite::Sprite()
	: curTime(0)
	, alive(true)
	, particle(false)
	, angle(0)
	, scale(1)
	, layer(0)
	, renderType(0)
	, texId(-1)
	, hasTrigger(false)
	, pivot(0.5f, 0.5f)
	, flip(false)
	, colour(1, 1, 1, 1)
{
}


Sprite::~Sprite()
{
}


void Sprite::setParent(Frame* _frame)
{
	frame = _frame;
}


bool Sprite::step(float time)
{
	curTime += time;
	if (!alive) {
		return false;
	} else { 		// Common case on fall-through, as per Intel recommendations
		if (anim) {
			anim->step(time);
			texId = anim->getTextureId();
		}
		return step(time, curTime);
	}
}


void Sprite::render(Renderer& renderer) const
{
	if (texId != -1) {
		Vector2f p = pivot;
		if (anim) p = anim->getPivot();
		renderer.drawImage(pos, p, texId, angle, scale, renderType, flip, colour);
	}
}


Frame& Sprite::getFrame() const
{
	return *frame;
}

void Sprite::playSound(String name, float volume)
{
	float w2 = getFrame().getMaxDist().x;
	float pan = (pos.x+w2)/(2.0f*w2);
	Audio::get()->play(name, pan, volume);
}


bool Sprite::isInsideField(float tolerance) const
{
	Vector2f limit = getFrame().getFieldSize() + Vector2f(tolerance, tolerance);
	return (abs(pos.y) < limit.y && abs(pos.x) < limit.x);
}


void Sprite::addTrigger(Collision::Mask mask, Collision::Trigger trigger)
{
	if (mask == Collision::None) throw Exception("Cannot specify collision with that group.");
	hasTrigger = true;
	triggers.push_back(Collision::TriggerPair(mask, trigger));
}


Collision::TriggerMap& Sprite::getTriggers()
{
	return triggers;
}


void Sprite::setAnimationGroup(String name)
{
	anim = shared_ptr<Animation::Player>(new Animation::Player(name));
}


void Sprite::setAnimationSequence(String name)
{
	if (anim) {
		anim->setSequence(name);
	}
}


void Sprite::setAnimationDirection(int n)
{
	if (anim) {
		anim->setDirection(n);
	}
}
