/*
 * 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 <boost/test/unit_test.hpp>
#include "ClientAdapter/ClientAdapter.h"
#include "../clientadapterproxy/ClientAdapterProxy.h"
#include "Common.h"
#include "MockFIFOWrapper.h"
#include "ManagementObjects/DevInfo.h"
#include "DataStorage/IDataStorage.h"
#include "Message.h"
#include "NotificationUpdaterImpl.h"
#include "SynchRunThread.h"

using namespace NS_DM_Client;

const int C_infinite = 1000000;

//-------------------------------------------------------------------------------------------

void OpenClientAdapterProxy(NS_DM_Client::ClientAdapterProxy* clientAdapterProxy)
{
	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_open);
	runThread.start();
	Wait();

	SimulateResponse(S_inFIFOWrapper, 1, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
	runThread.wait(C_infinite);
}
//-------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(GetDevInfoAsTNDS)
{
	std::cout << "START: GetDevInfoAsTNDS" << std::endl;
	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_inFIFOWrapper)); 
	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_outFIFOWrapper));

	NS_DM_Client::ClientAdapterProxy* clientAdapter = reinterpret_cast<NS_DM_Client::ClientAdapterProxy*>(CreateClientAdapter());
	NS_DM_Client::SetFIFOWrappers(*clientAdapter, S_inFIFOWrapper, S_outFIFOWrapper); // outgoing queue for stub = incoming queue for proxy
	OpenClientAdapterProxy(clientAdapter);

	std::string tndsDevInfo;	
	SynchRunThread runThread(*clientAdapter, NS_DM_Client::e_get, NS_DM_Client::e_devInfo, tndsDevInfo);
	runThread.start();
	Wait();

	// simulate adding response from stub
	std::string tndsDevInfoResponse;	
	FillDevInfoAsTnds(tndsDevInfoResponse);
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_okStatus, tndsDevInfoResponse);
	runThread.wait(C_infinite);

	clientAdapter->Release();
	std::cout << "END: GetDevInfoAsTNDS" << std::endl;
}
//-------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(SetDevInfoAsTNDS)
{
	std::cout << "START: SetDevInfoAsTNDS" << std::endl;
	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_inFIFOWrapper)); 
	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_outFIFOWrapper));

	NS_DM_Client::ClientAdapterProxy* clientAdapter = reinterpret_cast<NS_DM_Client::ClientAdapterProxy*>(CreateClientAdapter());
	NS_DM_Client::SetFIFOWrappers(*clientAdapter, S_inFIFOWrapper, S_outFIFOWrapper); // outgoing queue for stub = incoming queue for proxy
	OpenClientAdapterProxy(clientAdapter);

	std::string tndsDevInfo;	
	FillDevInfoAsTnds(tndsDevInfo);
	SynchRunThread runThread(*clientAdapter, NS_DM_Client::e_set, NS_DM_Client::e_devInfo, tndsDevInfo);
	runThread.start();
	Wait();

	// simulate adding response from stub
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
	runThread.wait(C_infinite);

	clientAdapter->Release();
	std::cout << "END: SetDevInfoAsTNDS" << std::endl;
}
//-------------------------------------------------------------------------------------------

 BOOST_AUTO_TEST_CASE(GetClientProfilies)
 {
 	std::cout << "START: GetClientProfilies" << std::endl;
 	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_outFIFOWrapper)); 
	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_inFIFOWrapper)); 
	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
 
 	OpenClientAdapterProxy(clientAdapterProxy);
 	std::vector<NS_DM_Client::ClientProfileInfo> profiles;
 	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_clientProfiles, NS_DM_Client::e_none, &profiles);
 	runThread.start();
 	Wait(5000);
 
 	std::string profilesString("Profile1 some description1 Profile2");
 	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_clientProfiles, NS_DM_Client::e_none, "2");
 	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_clientProfiles, NS_DM_Client::e_none, "Name1 Description1");
 	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_clientProfiles, NS_DM_Client::e_none, "Name2 Description2");
 	runThread.wait(C_infinite);
 
 	BOOST_CHECK(profiles.size() == 2);
 	BOOST_CHECK(profiles[0].m_name == "Name1");
 	BOOST_CHECK(profiles[1].m_name == "Name2");
 	BOOST_CHECK(profiles[0].m_description == "Description1");
 	BOOST_CHECK(profiles[1].m_description == "Description2");
 
 	clientAdapterProxy->Release();
 	TearDown();
 	std::cout << "END: GetClientProfilies" << std::endl;
 }
 //-------------------------------------------------------------------------------------------

 BOOST_AUTO_TEST_CASE(NotifyProvisionUpdate)
 {
 	std::cout << "START: NotifyProvisionUpdate" << std::endl;
 	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
 	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
 
 	OpenClientAdapterProxy(clientAdapterProxy);
	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_outFIFOWrapper)); // remove open from queue
	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_inFIFOWrapper)); // remove open from queue
 
	NS_DM_Client::NS_Common::EventEx notifyEvent;
 	NS_DM_Client::NotificationUpdaterImpl updater(&notifyEvent);
	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_notifyProvision, NS_DM_Client::e_none, &updater);
	runThread.start();
	Wait(5000);

 	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
 	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_notifyProvision, NS_DM_Client::e_none, "true");
 	runThread.wait(C_infinite);
	notifyEvent.wait();
 
 	BOOST_CHECK(updater.m_notifyProvisionUpdated);
 	clientAdapterProxy->Release();
 	TearDown();
 	std::cout << "END: NotifyProvisionUpdate" << std::endl;
 }
 //-------------------------------------------------------------------------------------------
 
 BOOST_AUTO_TEST_CASE(CheckForProvisionUpdate)
 {
 	std::cout << "START: CheckForProvisionUpdate" << std::endl;
 	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
 	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
 
 	OpenClientAdapterProxy(clientAdapterProxy);
 	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_outFIFOWrapper)); // remove open from queue
 
	NS_DM_Client::NS_Common::EventEx notifyEvent;
 	NS_DM_Client::NotificationUpdaterImpl updater(&notifyEvent);
  	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_checkProvision, NS_DM_Client::e_none, &updater);
  	runThread.start();
	Wait();

 	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
 	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_checkProvision, NS_DM_Client::e_none, "true");
	runThread.wait(C_infinite);
	notifyEvent.wait();
 
 	BOOST_CHECK(updater.m_provisionUpdated);
 	clientAdapterProxy->Release();
 	TearDown();
 	std::cout << "END: CheckForProvisionUpdate" << std::endl;
 }
 //-------------------------------------------------------------------------------------------
 
  BOOST_AUTO_TEST_CASE(GetDevInfo)
  {
  	std::cout << "START: GetDevInfo" << std::endl;
  	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
  	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
  
  	OpenClientAdapterProxy(clientAdapterProxy);
  	NS_DM_Client::ClearFIFO(dynamic_cast<NS_DM_Client::MockFIFOWrapper&>(*S_outFIFOWrapper)); // remove open from queue
  
  	NS_DM_Client::DevInfo deviceInfo;
  	deviceInfo.m_DevId = "devId1";
  	deviceInfo.m_Man = "Man1";
  	deviceInfo.m_Mod = "Mod1";
  	deviceInfo.m_DmV = "DmV1";
  	deviceInfo.m_Lang = "Lang1";
  	std::string deviceInfoXml;
  	deviceInfo.Serialize(deviceInfoXml);
  
  
  	NS_DM_Client::DevInfo realDeviceInfo;
  	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_get, NS_DM_Client::e_devInfo, &realDeviceInfo);
  	runThread.start();
  	Wait();
  
  	// simulate adding response from stub
  	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_get, NS_DM_Client::e_devInfo, deviceInfoXml);
  	runThread.wait(C_infinite);
  
  	BOOST_CHECK(realDeviceInfo.m_DevId == deviceInfo.m_DevId);
  	BOOST_CHECK(realDeviceInfo.m_Man == deviceInfo.m_Man);
  	BOOST_CHECK(realDeviceInfo.m_Mod == deviceInfo.m_Mod);
  	BOOST_CHECK(realDeviceInfo.m_DmV == deviceInfo.m_DmV);
  	BOOST_CHECK(realDeviceInfo.m_Lang == deviceInfo.m_Lang);
  
  	clientAdapterProxy->Release();
  	TearDown();
  	std::cout << "END: GetDevInfo" << std::endl;
  }
  //-------------------------------------------------------------------------------------------
 
  BOOST_AUTO_TEST_CASE(CloseClient)
  {
  	std::cout << "START: CloseClient" << std::endl;
  	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
  	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
  
  	OpenClientAdapterProxy(clientAdapterProxy);
  	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_close);
  	runThread.start();
  	Wait();
  
  	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
  	runThread.wait(C_infinite);
  
  	clientAdapterProxy->Release();
  	TearDown();
  	std::cout << "END: CloseClient" << std::endl;
  }
  //-------------------------------------------------------------------------------------------
  
  BOOST_AUTO_TEST_CASE(CreateClientAdapterProxy)
  {
  	std::cout << "START: CreateClientAdapterProxy" << std::endl;
  	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
  	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
  
  	BOOST_CHECK(clientAdapterProxy);
  	clientAdapterProxy->Release();
  	std::cout << "END: CreateClientAdapterProxy" << std::endl;
  }
  //-------------------------------------------------------------------------------------------
  
  BOOST_AUTO_TEST_CASE(OpenClient)
  {
  	std::cout << "START: OpenClient" << std::endl;
  	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
  	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
  
  	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_open);
  	runThread.start();
  	Wait();
  
  	SimulateResponse(S_inFIFOWrapper, 1, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
  	runThread.wait(C_infinite);
  
  	clientAdapterProxy->Release();
  	TearDown();
  	std::cout << "END: OpenClient" << std::endl;
  }
  //-------------------------------------------------------------------------------------------
  
  BOOST_AUTO_TEST_CASE(SetDevInfo)
  {
  	std::cout << "START: SetDevInfo" << std::endl;
  	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
  	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
  
  	OpenClientAdapterProxy(clientAdapterProxy);
  
  	NS_DM_Client::DevInfo deviceInfo;
  	deviceInfo.m_DevId = "devId";
  	deviceInfo.m_Man = "Man";
  	deviceInfo.m_Mod = "Mod";
  	deviceInfo.m_DmV = "DmV";
  	deviceInfo.m_Lang = "Lang";
  
  	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_set, NS_DM_Client::e_devInfo, &deviceInfo);
  	runThread.start();
  	Wait();
  
  	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
  	runThread.wait(C_infinite);
  
  	clientAdapterProxy->Release();
  	TearDown();
  
  	std::cout << "END: SetDevInfo" << std::endl;
  }
  //-------------------------------------------------------------------------------------------
  
  BOOST_AUTO_TEST_CASE(SetClientProfile)
  {
  	std::cout << "START: SetClientProfile" << std::endl;
  	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
  	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
  
  	OpenClientAdapterProxy(clientAdapterProxy);
  	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_set, NS_DM_Client::e_clientProfileName);
  	runThread.start();
  	Wait();
  
  	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
  	runThread.wait(C_infinite);
  
  	clientAdapterProxy->Release();
  	TearDown();
  	std::cout << "END: SetClientProfile" << std::endl;
  }
  //-------------------------------------------------------------------------------------------

// BOOST_AUTO_TEST_CASE(SetDevInfoWithoutOpening)
// {
// 	std::cout << "START: SetDevInfoWithoutOpening" << std::endl;
// 	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
// 	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
// 
// 	NS_DM_Client::DevInfo deviceInfo;
// 	SynchRunThread runThread(*clientAdapterProxy, NS_DM_Client::e_set, &deviceInfo);
// 	runThread.start();
// 	Wait();
// 
// 	clientAdapterProxy->Release();
// 	TearDown();
// 	std::cout << "END: SetDevInfoWithoutOpening" << std::endl;
// }
// //-------------------------------------------------------------------------------------------
