#include "Salamander.h"
#include "BackgroundManager.h"

#include "CameraEvent.h"
#include "Effect.h"

defineUniqueId(BackgroundManager);
BackgroundManager::BackgroundManager() :
	backgroundfalloffset_(0.0, 0.0),
	midgroundeffectcount_(40)
{
	
}

BackgroundManager::~BackgroundManager()
{

}

double BackgroundManager::moddouble(double numerator, double denominator)
{
	int result = static_cast<int>( numerator / denominator );
	return numerator - static_cast<double>( result ) * denominator;
}

bool BackgroundManager::startup()
{
	// parallax
	events().receive<BackgroundManager, CameraEvent>(this, &BackgroundManager::onCameraEvent);

	// graphics
	generateBackground();
	generateMidground();

	return true;
}

void BackgroundManager::generateMidground()
{
	// load graphics
	std::string filename;
	std::vector<Texture*> textures;
	std::ifstream midground("..\\data\\midground.txt");
	while(midground.good())
	{
		std::getline(midground, filename);
		textures.push_back(asset().load<Texture>("..\\data\\" + filename));
	}
	midground.close();

	// create some effects
	for(unsigned int i = 0; i < midgroundeffectcount_; i++)
	{
		Effect* effect = new Effect(Effect::MIDGROUND);
		effect->setScale(Vec2(32.0, 32.0));
		effect->setTexture(textures[rand() % textures.size()]);
		scene().addChild(*effect);
	}
	
}

void BackgroundManager::generateBackground()
{
	// the background!
	background_ = new Sprite();
	
	Stream& vcd = *(new Stream(StreamCoordinates::TypeId));
	vcd.add(*(new StreamCoordinates(0.0f,  0.0f)));
	vcd.add(*(new StreamCoordinates(0.0f, 10.0f)));
	vcd.add(*(new StreamCoordinates(10.0f, 0.0f)));
	vcd.add(*(new StreamCoordinates(10.0f,10.0f)));
	background_->addStream(vcd);

	background_->setColour(Colour(1.0, 1.0, 1.0, 1.0));
	background_->setTexture(asset().load<Texture>("..\\data\\background1.png"));
	background_->setReferenceFrame(Entity::WORLD);
	background_->setScale(Vec2(1024.0, 1024.0) * 10);
	scene().addChild(*background_);
}

bool BackgroundManager::shutdown()
{
   
	return true;
}

void BackgroundManager::frame()
{

	// falling
	backgroundfalloffset_.y_ -= application().delta() * 1000.0;
	if(backgroundfalloffset_.y_ < -1024.0) 
		backgroundfalloffset_.y_ = 0.0;
}

void BackgroundManager::onCameraEvent(const CameraEvent& event)
{
	// update parallax
	Vec2 translation = -event.getTranslation() * 0.5;

	translation.x_ = moddouble(translation.x_, 1024.0) + 512.0;
	translation.y_ = moddouble(translation.y_, 1024.0) + 512.0;

	translation += event.getTranslation();
	background_->setTranslation(translation + backgroundfalloffset_);
}