//
// C++ Implementation: Sun
//
// Description:
//
//
// Author: Erik Ogenvik <erik@ogenvik.org>, (C) 2004
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.//
//
#include "Sun.h"

#include "framework/Tokeniser.h"

#include "framework/ConsoleBackend.h"
#include <OgreVector.h>
#include <OgreSceneManager.h>
#include <OgreRoot.h>
#include <OgreSceneNode.h>




namespace Ember::OgreView::Environment {


Sun::Sun(Ogre::Camera* camera, Ogre::SceneManager* sceneMgr) :
		SetSunPosition("setsunposition", this, "Set the position of the sun."),
		SetSunColour("setsuncolour", this, "Set the colour of the sun."),
		SetAmbientLight("setambientlight", this, "Set the ambient light of the world."),
		mLensFlare(camera, sceneMgr) {
	mSun = sceneMgr->createLight("SunLight");
	mSun->setType(Ogre::Light::LT_DIRECTIONAL);

	if (sceneMgr->hasSceneNode("SunNode")) {
		mSunNode = sceneMgr->getSceneNode("SunNode");
	} else {
		mSunNode = sceneMgr->getRootSceneNode()->createChildSceneNode("SunNode");
	}

	mSunNode->attachObject(mSun);

	mLensFlare.setNode(mSunNode);
	mLensFlare.initialize();

//disable for now
// 	try {
// 		Ogre::ParticleSystem* sunParticle = sceneMgr->createParticleSystem("Sun", "Space/Sun");
// 		mSunNode->attachObject(sunParticle);
// 	} catch (const std::exception& ex) {
// 		logger->error("Error when creating sun. Message: " << ex.getFullDescription());
// 	}

	setSunPosition(Ogre::Vector3(-500, 300, -350));
	setSunColour(Ogre::ColourValue(1, 1, 0.7f)); //yellow
	//mSun->setSpecularColour(1, 1, 0.7); //yellow
	mSun->setCastShadows(true);
	mSun->setAttenuation(1000000, 1, 0, 0);

	//  sceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.35));
//	setAmbientLight(Ogre::ColourValue(0.6, 0.6, 0.6));

	Ogre::Root::getSingleton().addFrameListener(this);
	mLensFlare.setVisible(true);

}


Sun::~Sun() {
	Ogre::Root::getSingleton().removeFrameListener(this);

}

void Sun::runCommand(const std::string& command, const std::string& args) {
	if (SetSunPosition == command) {
		Tokeniser tokeniser;
		tokeniser.initTokens(args);
		std::string x = tokeniser.nextToken();
		std::string y = tokeniser.nextToken();
		std::string z = tokeniser.nextToken();

		if (x.empty() || y.empty() || z.empty()) {
			return;
		} else {
			Ogre::Vector3 position(Ogre::StringConverter::parseReal(x), Ogre::StringConverter::parseReal(y), Ogre::StringConverter::parseReal(z));
			setSunPosition(position);
		}
	} else if (SetSunColour == command) {
		Tokeniser tokeniser;
		tokeniser.initTokens(args);
		std::string r = tokeniser.nextToken();
		std::string b = tokeniser.nextToken();
		std::string g = tokeniser.nextToken();

		if (r.empty() || b.empty() || g.empty()) {
			return;
		} else {
			Ogre::ColourValue colour(Ogre::StringConverter::parseReal(r), Ogre::StringConverter::parseReal(b), Ogre::StringConverter::parseReal(g));
			setSunColour(colour);
		}

	} else if (SetAmbientLight == command) {
		Tokeniser tokeniser;
		tokeniser.initTokens(args);
		std::string r = tokeniser.nextToken();
		std::string b = tokeniser.nextToken();
		std::string g = tokeniser.nextToken();

		if (r.empty() || b.empty() || g.empty()) {
			return;
		} else {
			Ogre::ColourValue colour(Ogre::StringConverter::parseReal(r), Ogre::StringConverter::parseReal(b), Ogre::StringConverter::parseReal(g));
			setAmbientLight(colour);
		}

	}
}

bool Sun::frameEnded(const Ogre::FrameEvent& event) {
	mLensFlare.update();
	return true;
}


void Sun::setSunPosition(const Ogre::Vector3& position) {
	//mSun->setPosition(position);
	mSunNode->setPosition(position);
	Ogre::Vector3 dir = -mSunNode->getPosition();
	dir.normalise();
	mSunNode->setDirection(dir, Ogre::Node::TS_WORLD);
	EventUpdatedSunPosition.emit(this, position);
}

void Sun::setSunColour(const Ogre::ColourValue& colour) {
	mSun->setDiffuseColour(colour);
	mLensFlare.setBurstColour(colour);
	mLensFlare.setHaloColour(colour);
	EventUpdatedSunColour.emit(this, colour);
}

void Sun::setAmbientLight(const Ogre::ColourValue& colour) {
	if (mSun->_getManager()) {
		mSun->_getManager()->setAmbientLight(colour);
	}
	EventUpdatedAmbientLight.emit(this, colour);
}

}



