#include "Salamander.h"
#include "Effect.h"

#include "CameraEvent.h"

Effect::Effect(EffectType type) : Sprite(),
	type_(type),
	wraplength_(0.6)
{
	// for wrapping
	events().receive<Effect, CameraEvent>(this, &Effect::onCameraEvent);

	// for textures
	Stream& vcd = *(new Stream(StreamCoordinates::TypeId));
	vcd.add(*(new StreamCoordinates(0.0f, 0.0f)));
	vcd.add(*(new StreamCoordinates(0.0f, 1.0f)));
	vcd.add(*(new StreamCoordinates(1.0f, 0.0f)));
	vcd.add(*(new StreamCoordinates(1.0f, 1.0f)));
	addStream(vcd);

	setReferenceFrame(Entity::WORLD);
	setColour(Colour(1.0, 1.0, 1.0, 1.0));

	value1_ = (rand() % 1000) * 0.001;
	value2_ = (rand() % 1000) * 0.001;
	value3_ = (rand() % 1000) * 0.001;

	setTranslation(Vec2(rand() % 5000, rand() % 5000));

	// extra stuff
	if(type_ == FOREGROUND)
		wraplength_ = 5.0;

	if(type_ == RAIN)
	{
		value1_ = 0.5 + PI;
		setRotation(value1_);
		setColour(Colour(1.0, 1.0, 1.0, 0.2));
	}
}

Effect::~Effect()
{
	
}

void Effect::frame()
{
	Sprite::frame();

	if(type_ == MIDGROUND)
		animateMidground();
	if(type_ == FOREGROUND)
		animateForeground();
	if(type_ == RAIN)
		animateRain();
}

void Effect::animateMidground()
{
	value1_ += application().delta();
	
	// translation
	Vec2 translation = getTranslation();
	translation += Mat2(value1_ * 10.0) * Vec2(0.0, 1.0 * application().delta() * value2_ * 10.0);	// circles
	translation += Mat2(value2_ * 10.0) * Vec2(0.0, application().delta() * value3_ * 100.0);		// random movement
	translation += Vec2(0.0, -application().delta() * value2_ * 1000.0);							// upwards
	setTranslation(translation);

	// rotation
	double rotation = getRotation();
	rotation -= value2_ * application().delta();
	setRotation(rotation);
}

void Effect::animateForeground()
{
	// translation
	Vec2 translation = getTranslation();
	translation += Vec2(0.0, -application().delta() * (value1_ + 1.0) * 2000.0);					// upwards
	setTranslation(translation);

}

void Effect::animateRain()
{
	// translation
	Vec2 translation = getTranslation();
	translation += Mat2(value1_) * Vec2(0.0, -application().delta() * (value2_ + 0.5) * getScale().x_ * 5.0);		// sidewaysish
	setTranslation(translation);
}

void Effect::onCameraEvent(const CameraEvent& event)
{
	// update parallax
	Vec2 difference = (event.getTranslation() - camera_) * 0.25;
	camera_ = event.getTranslation();

	Vec2 translation = getTranslation();
	translation += difference;

	// if we're outside bounds, wrap
	Vec2 lowerbound = event.getTranslation() - screen().getResolution() * wraplength_;
	Vec2 upperbound = event.getTranslation() + screen().getResolution() * wraplength_;

	if(translation.x_ < lowerbound.x_) translation.x_ += (upperbound.x_ - lowerbound.x_);
	if(translation.x_ > upperbound.x_) translation.x_ -= (upperbound.x_ - lowerbound.x_);
	if(translation.y_ < lowerbound.y_) translation.y_ += (upperbound.y_ - lowerbound.y_);
	if(translation.y_ > upperbound.y_) translation.y_ -= (upperbound.y_ - lowerbound.y_);

	setTranslation(translation);
}
