#include "MockFIFOWrapper.h"
#include "../clientadapterproxy/ClientAdapterProxy.h"
#include "ClientAdapter/ClientAdapterStub.h"

#include "common/Buffer.h"
#include "Message.h"

namespace NS_DM_Client
{
	void ClearFIFO(MockFIFOWrapper& fifoWrapper)
	{
		size_t end(fifoWrapper.m_queue.size());
		for (size_t i = 0; i != end; ++i)
		{
			fifoWrapper.m_queue.pop();
		}
	}
	//-------------------------------------------------------------------------------------------

	void SetFIFOWrappers(ClientAdapterProxy& clientAdapterProxy, NS_DM_Client::IFIFOWrapper* inFIFOWrapper, 
		NS_DM_Client::IFIFOWrapper* outFIFOWrapper)
	{
 		if (clientAdapterProxy.m_inFIFOWrapper)
		{
			delete clientAdapterProxy.m_inFIFOWrapper;
			clientAdapterProxy.m_inFIFOWrapper = 0;
		}
		clientAdapterProxy.m_inFIFOWrapper = inFIFOWrapper;

 		if (clientAdapterProxy.m_outFIFOWrapper)
		{
			delete clientAdapterProxy.m_outFIFOWrapper;
			clientAdapterProxy.m_outFIFOWrapper = 0;
		}
		clientAdapterProxy.m_outFIFOWrapper = outFIFOWrapper;

	}
	//-------------------------------------------------------------------------------------------

	void SetFIFOWrappers(ClientAdapterStub& clientAdapterStub, NS_DM_Client::IFIFOWrapper* inFIFOWrapper, 
		NS_DM_Client::IFIFOWrapper* outFIFOWrapper)
	{
 		if (clientAdapterStub.m_inFIFOWrapper)
 			delete clientAdapterStub.m_inFIFOWrapper;
		clientAdapterStub.m_inFIFOWrapper = inFIFOWrapper;

 		if (clientAdapterStub.m_outFIFOWrapper)
			delete clientAdapterStub.m_outFIFOWrapper;
		clientAdapterStub.m_outFIFOWrapper = outFIFOWrapper;

	}
	//-------------------------------------------------------------------------------------------

	IFIFOWrapper* CreateFIFOWrapper(bool serverSide/* = false*/)
	{
		return 0;
		//return new MockFIFOWrapper();
	}
	//-------------------------------------------------------------------------------------------

	MockFIFOWrapper::MockFIFOWrapper(): m_isFreezed(true)
	{
	}
	//-------------------------------------------------------------------------------------------

	MockFIFOWrapper::~MockFIFOWrapper()
	{
	}
	//-------------------------------------------------------------------------------------------

	StatusCode MockFIFOWrapper::Open(const String& name, bool readMode, bool blockedMode, bool immediateOpen/* = false*/)
	{
		return e_Ok;
	}
	//-------------------------------------------------------------------------------------------

	StatusCode MockFIFOWrapper::Read(Buffer& buffer, bool exitIfNoWriter/* = false*/)
	{
		if (m_queue.empty())
			freeze();

		if (m_queue.empty())
			return e_Failed;

		m_isFreezed = true;
		size_t bufferSize = buffer.Size(); 
		QueueData data = m_queue.front();
		if (data.size() == bufferSize)
		{
			buffer.Allocate(data.size());
			memcpy(buffer.GetPointer(), &data[0], data.size());
			m_queue.pop();
			return e_Ok;
		}
		return e_Failed;
	}
	//-------------------------------------------------------------------------------------------

	void MockFIFOWrapper::freeze()
	{
		while (m_isFreezed)
		{
		}
	}
	//-------------------------------------------------------------------------------------------

	void MockFIFOWrapper::FreezeOff()
	{
		m_isFreezed = false;
	}
	//-------------------------------------------------------------------------------------------

	StatusCode MockFIFOWrapper::Write(const Buffer& buffer, bool exitIfNoReader/* = false*/)
	{
		return e_Failed;
	}
	//-------------------------------------------------------------------------------------------

	StatusCode MockFIFOWrapper::Write(const void* buffer, size_t length, bool exitIfNoReader/* = false*/)
	{
		// write header and then body = 2 messages in queue
		QueueData header;
		size_t headerSize = Message::GetHeaderSize();
		header.resize(headerSize);
		memcpy(&header[0], buffer, headerSize);
		m_queue.push(header);

		QueueData body;
		size_t bodySize = length - headerSize;
		if (bodySize != 0)
		{
			body.resize(bodySize);
			memcpy(&body[0], reinterpret_cast<const char*>(buffer) + headerSize, bodySize);
			m_queue.push(body);
		}

		return e_Ok;
	}
	//-------------------------------------------------------------------------------------------

	StatusCode MockFIFOWrapper::Close()
	{
		return e_Ok;
	}
	//-------------------------------------------------------------------------------------------

	void MockFIFOWrapper::Release()
	{
		FreezeOff();
		//delete this;
	}
	//-------------------------------------------------------------------------------------------

	size_t MockFIFOWrapper::GetMessagesCount() const
	{
		return m_queue.size();
	}
	//-------------------------------------------------------------------------------------------

	StatusCode MockFIFOWrapper::open()
	{
		return e_Ok;
	}
}
