//	LuaClasses.cpp - Used to register our various helper structs/classes.
//  ----------------------------------------------------------------------------
//	This file is part of 'NiallsAVLib', base code for any kind of audiovisual
//	apps.
//	Copyright (C) 2013  Niall Moody
//	
//	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 3 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, see <http://www.gnu.org/licenses/>.
//	----------------------------------------------------------------------------

#include "ColourHelpers.h"
#include "ThreeFloats.h"
#include "MiscHelper.h"
#include "LuaClasses.h"
#include "TwoFloats.h"
#include "Random.h"

extern "C" {
  #include "lua.h"
  #include "lualib.h"
  #include "lauxlib.h"
}

#include "luabind/luabind.hpp"
#include "luabind/operator.hpp"

//------------------------------------------------------------------------------
void LuaClasses::registerLuaClasses(lua_State *luaState)
{
	//TwoFloats.
	luabind::module(luaState)
	[
		luabind::class_<TwoFloats>("TwoFloats")
			.def_readwrite("x", &TwoFloats::x)
			.def_readwrite("y", &TwoFloats::y)
			.def(luabind::constructor<>())
			.def(luabind::constructor<float>())
			.def(luabind::constructor<float, float>())
			.def(luabind::constructor<TwoFloats>())
			.def(luabind::self + luabind::other<TwoFloats>())
			.def(luabind::self + float())
			.def(luabind::self - luabind::other<TwoFloats>())
			.def(luabind::self - float())
			.def(luabind::self * luabind::other<TwoFloats>())
			.def(luabind::self * float())
			.def(luabind::self / luabind::other<TwoFloats>())
			.def(luabind::self / float())
			.def(luabind::self == luabind::other<TwoFloats>())
			.def(luabind::self == float())
			.def("abs", &TwoFloats::abs)
			.def("getDistance", &TwoFloats::getDistance)
			.def("getDistanceSquared", &TwoFloats::getDistanceSquared)
			.def("getMagnitude", &TwoFloats::getMagnitude)
			.def("getAngle", (float(TwoFloats::*)(const TwoFloats&) const)&TwoFloats::getAngle)
			.def("getAngle", (float(TwoFloats::*)() const)&TwoFloats::getAngle)
			.def("perpendicular", &TwoFloats::perpendicular)
			.def("normal", &TwoFloats::normal)
			.def("dotProduct", &TwoFloats::dotProduct)
			.def("crossProduct", &TwoFloats::crossProduct)
			.def("mirror", &TwoFloats::mirror)
			.def("project", &TwoFloats::project)
			.def("projectDir", &TwoFloats::projectDir)
			.def("isWithin", &TwoFloats::isWithin)
	];

	//ThreeFloats.
	luabind::module(luaState)
	[
		luabind::class_<ThreeFloats>("ThreeFloats")
			.def_readwrite("x", &ThreeFloats::x)
			.def_readwrite("y", &ThreeFloats::y)
			.def_readwrite("z", &ThreeFloats::z)
			.def(luabind::constructor<>())
			.def(luabind::constructor<float>())
			.def(luabind::constructor<float, float, float>())
			.def(luabind::constructor<ThreeFloats>())
			.def(luabind::self + luabind::other<ThreeFloats>())
			.def(luabind::self + float())
			.def(luabind::self - luabind::other<ThreeFloats>())
			.def(luabind::self - float())
			.def(luabind::self * luabind::other<ThreeFloats>())
			.def(luabind::self * float())
			.def(luabind::self / luabind::other<ThreeFloats>())
			.def(luabind::self / float())
			.def(luabind::self == luabind::other<ThreeFloats>())
			.def("getDistance", &ThreeFloats::getDistance)
	];

	//Random.
	luabind::module(luaState)
	[
		luabind::class_<Random>("Random")
			.def(luabind::constructor<>())
			.def("getRandomInt", &Random::getRandomInt)
			.def("getRandomFloat", &Random::getRandomFloat)
			.scope
			[
				luabind::def("getGlobal", &Random::getGlobal)
			]
	];

	//MiscHelper.
	luabind::module(luaState)
	[
		luabind::def("fakeLog", &fakeLog),
		luabind::def("fakeExp", &fakeExp),
		luabind::def("fakeSine", &fakeSine),
		//luabind::def("round", &round),
		luabind::def("isPowerOfTwo", &isPowerOfTwo),
		luabind::def("powerOfTwo", &powerOfTwo)
	];

	//ColourHelpers.
	luabind::module(luaState)
	[
		luabind::def("hslToRgb", &ColourHelpers::hslToRgb),
		luabind::def("rgbToHsl", &ColourHelpers::rgbToHsl)
	];

	//Debug output.
	luabind::module(luaState)
	[
		luabind::def("writeDebugOutput", &LuaClasses::writeDebugOutput)
	];
}

//------------------------------------------------------------------------------
std::string& LuaClasses::getDebugOutput()
{
	static std::string retval;

	return retval;
}

//------------------------------------------------------------------------------
void LuaClasses::writeDebugOutput(const std::string& text)
{
	LuaClasses::getDebugOutput() = text;
}
