/*
 * Copyright (C) 2009 - 2010 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * 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 Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */


#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;
	}
}
