#include <boost/test/unit_test.hpp>
#include "ClientAdapter/ClientAdapter.h"
#include "../clientadapterproxy/ClientAdapterProxy.h"
#include "ClientAdapter/ProvisionInfo.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(5000);

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

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_notifyProvisioningUpdate, NS_DM_Client::e_none, &updater);
	NS_DM_Client::ProvisionInfoRequest provisionInfo("SomeUri", false, NS_DM_Client::e_Add, NS_DM_Client::e_sessionStart);
	runThread.SetProvisionInfo(provisionInfo);
	runThread.start();
	Wait(5000);

	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_okStatus);
	std::vector<std::string> URIs;
	URIs.push_back("SomeUri1");
	URIs.push_back("SomeUri2");
	NS_DM_Client::ProvisionInfoResponse response(URIs, NS_DM_Client::e_Add, NS_DM_Client::e_sessionStart, NS_DM_Client::e_Ok);
	std::string strResponse;
	response.Serialize(strResponse);
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_notifyProvisioningUpdate, NS_DM_Client::e_none, strResponse);
	runThread.wait(C_infinite);
	notifyEvent.wait();

	BOOST_CHECK(updater.m_notifyProvisionUpdated);
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
	clientAdapterProxy->Release();
	TearDown();
	std::cout << "END: NotifyProvisionUpdate" << std::endl;
}
//-------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(GetDevInfoAsTNDS)
{
	std::cout << "START: GetDevInfoAsTNDS" << std::endl;
	NS_DM_Client::ClientAdapterProxy* clientAdapterProxy = (NS_DM_Client::ClientAdapterProxy*)CreateClientAdapter();
	NS_DM_Client::SetFIFOWrappers(*clientAdapterProxy, S_inFIFOWrapper, S_outFIFOWrapper);
	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

	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

	std::string tndsDevInfo;	
	SynchRunThread runThread(*clientAdapterProxy, 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);

	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
	clientAdapterProxy->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);

	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
	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");
 
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
 	clientAdapterProxy->Release();
 	TearDown();
 	std::cout << "END: GetClientProfilies" << 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_DmV == deviceInfo.m_DmV);
  	BOOST_CHECK(realDeviceInfo.m_Lang == deviceInfo.m_Lang);
  
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
  	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);
  
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
  	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);
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
 	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);
  
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
  	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_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);
  
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
  	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);
  
	SimulateResponse(S_inFIFOWrapper, 2, NS_DM_Client::e_status, NS_DM_Client::e_stopWaitingStatus);
 	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;
// }
// //-------------------------------------------------------------------------------------------
