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

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

using namespace std;
using namespace LiquidRobotics::SMACFramework;

namespace LiquidRobotics {
namespace LuaWrapper {

LWForwardTimeoutInternalCmd::LWForwardTimeoutInternalCmd(TCon& _ctrl, const string& _cmd, const string& _instanceName, const string& _timerName)
: LWConcreteCmd(_ctrl)
, ctrl(_ctrl)
, cmd(_cmd)
, instanceName(_instanceName)
, timerName(_timerName)
{
}

LWForwardTimeoutInternalCmd::~LWForwardTimeoutInternalCmd()
{
}

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

	try
	{
		SignalStarted();

		LuaInstancePtr inst = ctrl.GetLuaInstance(instanceName);
		const LuaInstance::StackStateHolder stateHolder(*inst);
		const string functionName = "SMCReportTimeout";
		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());
		}

		inst->pushlstring(timerName);
		inst->pcall(1, LUA_MULTRET, 0, true);

		const int numResults = inst->gettop()-stateHolder.top;

		msg << "numResults=" << numResults;

		for (int i = 0; i < numResults; ++i)
		{
			LuaInstance::StringPtr res = inst->tolstring(i-numResults);

			msg << " " << i << "=" << (res ? *res : "nil");
		}

		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");
	}
}

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

}
}
