//-------------------------------------------------------------------------------------------------
// <copyright file="LWForwardLocationInternalCmd.cpp" company="LiquidRobotics">
//  Copyright (c) Liquid Robotics Corporation, confidential and proprietary.  All rights reserved. 
// </copyright>
//
// <summary>
//	Implementation of LWForwardLocationInternalCmd, a delegate class that carries
//	GPS data that was just received and is queued up on the lua instance specific
//	thread.  When it runs, it forwards the data to the script on the SMCReportLocation
//	method.
// </summary>
//
// <owner>Mike Cookson</owner>
//-------------------------------------------------------------------------------------------------

#include "LWController.h"
#include "LWForwardLocationInternalCmd.h"
#include "LWLocationTable.h"
#include "LqrSMACLogger.h"
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace LiquidRobotics::SMACFramework;

static const string functionName = "SMCReportLocation";

namespace LiquidRobotics {
namespace LuaWrapper {

LWForwardLocationInternalCmd::LWForwardLocationInternalCmd(TCon& _ctrl, const string& _cmd, const string& _instanceName, double _lat, double _lon)
: LWConcreteCmd(_ctrl)
, ctrl(_ctrl)
, cmd(_cmd)
, instanceName(_instanceName)
, lat(_lat)
, lon(_lon)
{
}

LWForwardLocationInternalCmd::~LWForwardLocationInternalCmd()
{
}

void LWForwardLocationInternalCmd::Execute()
{
	typedef boost::shared_ptr<LuaInstance> LuaInstancePtr;

	try
	{
		SignalStarted();

		LuaInstancePtr inst = ctrl.GetLuaInstance(instanceName);
		const LuaInstance::StackStateHolder stateHolder(*inst);
		stringstream msg;

		inst->getglobal(functionName.c_str());

		if (!inst->isfunction(-1))
		{
			msg << functionName << " is not a function/procedure in instance " << instanceName;
			throw invalid_argument(msg.str());
		}

		PushLocationTable(*inst, true, lat, lon);
		inst->pcall(1, LUA_MULTRET, 0, true);
		SetException(TEx::NoException, "");
	}
	catch(exception& ex)
	{
		const int exNum = TEx::ExceptionToNumber(ex);

		stringstream msg;
		msg << "caught exception " << typeid(ex).name() << " '" << ex.what() << "'";

		SetException(exNum, msg.str());
	}
	catch(...)
	{
		TEx::NotReady exc("");
		const int exNum = TEx::ExceptionToNumber(exc);

		SetException(exNum, "caught unknown exception");
	}
}

// determines if the instance wants fowarded GPS info
bool LWForwardLocationInternalCmd::InstanceWantsGPSForwarding(LuaInstance& L)
{
	const LuaInstance::StackStateHolder stateHolder(L);
	bool result;

	L.getglobal(functionName.c_str());
	result = !!L.isfunction(-1);
	return result;
}

// get the output of the command
string LWForwardLocationInternalCmd::GetResult()
{
	DoThrow();
	return "OK";
}

}
}
