#include "OwnCommandProcessor.h"
// ProtoGenWrapper
#include <ComChannel.h>
#include <Command.h>
using namespace OpenTestSystem::OtxDiagManager::Common;

bool OwnCommandProcessor::_isExecuting = false;
std::queue <Command> OwnCommandProcessor::_cmdQueue;
std::mutex OwnCommandProcessor::_mutex;

OwnCommandProcessor::OwnCommandProcessor()
	: OwnCommandProcessor(nullptr)
{
}

OwnCommandProcessor::OwnCommandProcessor(OpenTestSystem::OtxDiagManager::Common::IDiagRuntimeSystem * drs)
	: _diagRuntimeSystem(drs)
{
}

OwnCommandProcessor::~OwnCommandProcessor()
{
	delete _diagRuntimeSystem;
}

Result * OwnCommandProcessor::Execute(const Command & command)
{
	if (_diagRuntimeSystem != nullptr)
		return _diagRuntimeSystem->Execute(command);
	return nullptr;
}

Result* OwnCommandProcessor::ExecuteAsync(const Command& command)
{
	AddCommandToQueue(command);

	if (_isExecuting == false)
	{
		do
		{
			_isExecuting = true;
			if (_diagRuntimeSystem != nullptr)
			{
				Command cmd = PopCommandFromQueue();
				_diagRuntimeSystem->ExecuteAsync(cmd);
			}
		}
		while (GetCommandQueueSize() != 0);

		_isExecuting = false;
	}

	return nullptr;
}

void OwnCommandProcessor::SetAsyncResultHandler(std::function<void(const Result&)> handler)
{
	if (_diagRuntimeSystem != nullptr)
		_diagRuntimeSystem->SetAsyncResultHandler(handler);
}

void OwnCommandProcessor::SetExceptionHandler(std::function<void(const Exception&)> handler)
{
	if (_diagRuntimeSystem != nullptr)
		_diagRuntimeSystem->SetExceptionHandler(handler);
}

void OwnCommandProcessor::AddCommandToQueue(const Command& command)
{
	std::unique_lock<std::mutex> lock(_mutex);
	_cmdQueue.push(command);
}

Command OwnCommandProcessor::PopCommandFromQueue()
{
	std::unique_lock<std::mutex> lock(_mutex);
	Command cmd = _cmdQueue.front();
	_cmdQueue.pop();

	return cmd;
}

std::size_t OwnCommandProcessor::GetCommandQueueSize()
{
	std::unique_lock<std::mutex> lock(_mutex);
	return _cmdQueue.size();
}
