/*
 * 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 "ClientAdapter/ClientAdapter.h"
#include "ManagementObjects/DevInfo.h"
#include "ManagementObjects/DevDetail.h"
#include "ManagementObjects/DMAcc.h"
#include "ManagementObjects/WiMAX.h"
#include "ManagementObjects/WiMAXSupp.h"
#include "ManagementObjects/WiMAX_Diagnostics.h"
#include <iostream>
#include "../UTestClientAdapter/NotificationUpdaterImpl.h"
#include "Event.h"
#include "Utils.h"

void HandleGetRequest(const std::string& requestType, NS_DM_Client::IClientAdapter* clientAdapter)
{
	std::cout << "Received request = " << requestType << std::endl;
	bool res = false;
	NS_DM_Client::IMgmtObject* mgmtObject = 0;
	if (requestType == "DevInfo")
	{
		mgmtObject = new NS_DM_Client::DevInfo();
		res = clientAdapter->GetDeviceInfo(dynamic_cast<NS_DM_Client::DevInfo&>(*mgmtObject));
	} 
	else if (requestType == "DevDetail")
	{
		mgmtObject = new NS_DM_Client::DevDetail();
		res = clientAdapter->GetDeviceDetail(dynamic_cast<NS_DM_Client::DevDetail&>(*mgmtObject));
	}
	else if (requestType == "DMAcc")
	{
		mgmtObject = new NS_DM_Client::DMAcc();
		res = clientAdapter->GetDMAccount(dynamic_cast<NS_DM_Client::DMAcc&>(*mgmtObject));
	}
	else if (requestType == "WiMAXSupp")
	{
		mgmtObject = new NS_DM_Client::WiMAXSupp();
		res = clientAdapter->GetWiMAXSupp(dynamic_cast<NS_DM_Client::WiMAXSupp&>(*mgmtObject));
	}
	else if (requestType == "WiMAX")
	{
		mgmtObject = new NS_DM_Client::WiMAX();
		res = clientAdapter->GetWiMAX(dynamic_cast<NS_DM_Client::WiMAX&>(*mgmtObject));
	}
	else if (requestType == "EMSK")
	{
		std::cout << "request GetEMSK is not supported" << std::endl;
/*		
		void* someStrBuffer = 0;
		size_t size;
		res = clientAdapter->GetEMSK(someStrBuffer, size);
		if (!res)
		{
			std::cout << "Failed to handle request GetEMSK" << std::endl;
			return;
		}
		if (size != 0)
		{
			char* buffer = new char[size + 1];
			memset(buffer, 0, size + 1);
			memcpy(buffer, someStrBuffer, size);
			std::cout << "Response on GetEMSK: \n" << buffer << std::endl;
			delete [] buffer;
			delete [] someStrBuffer;
		}
		else
			std::cout << "Empty EMSK was returned \n" << std::endl;
*/
		return;

	}
	else // assume requestType = uri
	{
		std::string mgmtTree;
		res = clientAdapter->GetMgmtTree(requestType, mgmtTree);
		if (!res)
		{
			std::cout << "Failed to handle request" << std::endl;
			return;
		}
		std::cout << "Response MgmtTree: \n" << mgmtTree.c_str() << std::endl;
		return;
	}

	if (!res)
	{
		std::cout << "Failed to handle request" << std::endl;
		return;
	}
	std::string xmlResult;
	mgmtObject->Serialize(xmlResult);
	std::cout << "Response: " << xmlResult.c_str() << std::endl;
	delete mgmtObject;

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

void FillInDevInfo(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";
}
//-------------------------------------------------------------------------------------------

void FillInDevDetail(NS_DM_Client::DevDetail& deviceDetail)
{
	deviceDetail.m_URI.m_MaxDepth = 22;
	deviceDetail.m_URI.m_MaxSegLen = 23;
	deviceDetail.m_URI.m_MaxTotLen = 24;
	deviceDetail.m_DevTyp = "test dev type";
	deviceDetail.m_OEM = "test zte";
	deviceDetail.m_FwV = "test FwV";
	deviceDetail.m_SwV = "test SwV";
	deviceDetail.m_HwV = "test Hwv";
	deviceDetail.m_LrgObj = true;
}
//-------------------------------------------------------------------------------------------

void FillInWiMAXSupp(NS_DM_Client::WiMAXSupp& wimaxSupp)
{
	NS_DM_Client::Operator oper;

	NS_DM_Client::RootCA rootCA;
	rootCA.m_CertID = "certID";
	oper.m_RootCA.push_back(rootCA);

	oper.m_TO_IP_REF = "ref";

	NS_DM_Client::EAP eap;
	eap.m_SERVER_REALMS.push_back("ServerRealm");

	eap.m_VFY_SERVER_REALM = 1;

	NS_DM_Client::CERT cert;
	cert.m_CERT_TYPE = "CERT_TYPE";
	eap.m_CERT.push_back(cert);
	oper.m_SubscriptionParameters.m_Primary.m_EAP.push_back(eap);

	NS_DM_Client::OtherSubscriptions otherSubs;
	otherSubs.m_EAP.push_back(eap);
	otherSubs.m_Activated = 1;
	otherSubs.m_Name = "Other Subcription name";
	oper.m_SubscriptionParameters.m_OtherSubscriptions.push_back(otherSubs);

	oper.m_NetworkParameters.m_H_NSP.push_back(1);
	oper.m_NetworkParameters.m_H_NSP.push_back(2);

	NS_DM_Client::ChannelPlanEntries channelPlanEntries; 
	channelPlanEntries.m_BW = 10;
	oper.m_NetworkParameters.m_ChannelPlan.m_Entries.push_back(channelPlanEntries);

	std::string name1("SomeOperator1");
	std::string name2("SomeOperator2");
	wimaxSupp.m_Operator[name1] = oper;
	wimaxSupp.m_Operator[name2] = oper;
}
//-------------------------------------------------------------------------------------------

void FillInWiMAXDiagnostics(NS_DM_Client::NS_DM_Diagnostics::WiMAX_Diagnostics& wimaxDiagnostics)
{
	wimaxDiagnostics.Execute();
}

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

void HandleSetRequest(const std::string& requestType, NS_DM_Client::IClientAdapter* clientAdapter)
{
	std::cout << "Received request = " << requestType << std::endl;
	NS_DM_Client::IMgmtObject* mgmtObject = 0;
	bool res = false;
	if (requestType == "DevInfo")
	{
		mgmtObject = new NS_DM_Client::DevInfo();
		NS_DM_Client::DevInfo& deviceInfo = dynamic_cast<NS_DM_Client::DevInfo&>(*mgmtObject);
		FillInDevInfo(deviceInfo);
		res = clientAdapter->SetDeviceInfo(deviceInfo);
	}
	else if (requestType == "DevDetail")
	{
		mgmtObject = new NS_DM_Client::DevDetail();
		NS_DM_Client::DevDetail& deviceDetail = dynamic_cast<NS_DM_Client::DevDetail&>(*mgmtObject);
		FillInDevDetail(deviceDetail);
		res = clientAdapter->SetDeviceDetail(dynamic_cast<NS_DM_Client::DevDetail&>(deviceDetail));
	}
	else if (requestType == "DMAcc")
	{
		mgmtObject = new NS_DM_Client::DMAcc();
		res = clientAdapter->SetDMAccount(dynamic_cast<NS_DM_Client::DMAcc&>(*mgmtObject));
	}
	else if (requestType == "WiMAXSupp")
	{
		mgmtObject = new NS_DM_Client::WiMAXSupp();
		NS_DM_Client::WiMAXSupp& wimaxSupp = dynamic_cast<NS_DM_Client::WiMAXSupp&>(*mgmtObject);
		FillInWiMAXSupp(wimaxSupp);
		res = clientAdapter->SetWiMAXSupp(wimaxSupp);
	}
	else if (requestType == "WiMAX")
	{
		mgmtObject = new NS_DM_Client::WiMAX();
		res = clientAdapter->SetWiMAX(dynamic_cast<NS_DM_Client::WiMAX&>(*mgmtObject));
	}
	else if (requestType == "EMSK")
	{
		std::string someStrBuffer("Some string buffer");
		res = clientAdapter->SetEMSK(someStrBuffer.c_str(), someStrBuffer.size());
	}
	else if (requestType == "DeviceID")
	{
		std::string someStrBuffer("Some DeviceID");
		res = clientAdapter->SetDeviceID(someStrBuffer.c_str(), someStrBuffer.size());
	}
	else // assume requestType = fileName (where Management Tree is located)
	{
		std::string mgmtTree;
		ReadFromFile(requestType, mgmtTree);
		res = clientAdapter->SetMgmtTree(mgmtTree);
		if (!res)
		{
			std::cout << "Failed to handle request" << std::endl;
			return;
		}
	}

	if (requestType == "WiMAX_Diagnostics")
	{
		mgmtObject = new NS_DM_Client::NS_DM_Diagnostics::WiMAX_Diagnostics;
		NS_DM_Client::NS_DM_Diagnostics::WiMAX_Diagnostics& wimaxDiagnostics = dynamic_cast<NS_DM_Client::NS_DM_Diagnostics::WiMAX_Diagnostics&>(*mgmtObject);
		FillInWiMAXDiagnostics(wimaxDiagnostics);
		res = clientAdapter->SetWiMAXDiagnostics(wimaxDiagnostics);
	}

	std::cout << "Response: " << res << std::endl;
}
//-------------------------------------------------------------------------------------------

void HandleOpenRequest(NS_DM_Client::IClientAdapter* clientAdapter)
{
	std::cout << "Received Open request." << std::endl;
	bool res = clientAdapter->Open();
	if (!res)
	{
		std::cout << "Failed to open" << std::endl;
		return;
	}
	std::cout << "Response: " << res << std::endl;
}
//-------------------------------------------------------------------------------------------

void HandleCheckFirmwareRequest(NS_DM_Client::IClientAdapter* clientAdapter)
{
	std::cout << "Received CheckFirmware request." << std::endl;
	NS_DM_Client::NS_Common::EventEx notifyEvent;
	NS_DM_Client::NotificationUpdaterImpl* updater = new NS_DM_Client::NotificationUpdaterImpl(&notifyEvent); 
	bool res = clientAdapter->CheckForFirmwareUpdate(updater);
	if (!res)
	{
		std::cout << "Failed to CheckForFirmwareUpdate" << std::endl;
		return;
	}
	std::cout << "Response: " << res << std::endl;
	notifyEvent.wait();
	delete updater;
}
//-------------------------------------------------------------------------------------------

void HandleStartDMSessionRequest(NS_DM_Client::IClientAdapter* clientAdapter)
{
	std::cout << "Received startDMSession request." << std::endl;
	NS_DM_Client::NS_Common::EventEx notifyEvent;
	NS_DM_Client::NotificationUpdaterImpl* updater = new NS_DM_Client::NotificationUpdaterImpl(&notifyEvent); 
	bool res = clientAdapter->StartDMSession(updater);
	if (!res)
	{
		std::cout << "Failed to StartDMSession" << std::endl;
		return;
	}
	std::cout << "Response: " << res << std::endl;
	notifyEvent.wait();
	delete updater;
}
//-------------------------------------------------------------------------------------------

void HandleNetworkEntry(NS_DM_Client::IClientAdapter* clientAdapter, int hnspID, const char* operatorName)
{
	std::cout << "Received NetworkEntry request." << std::endl;
	bool res = clientAdapter->HandleNetworkEntry(hnspID, operatorName);
	if (!res)
	{
		std::cout << "Failed to HandleNetworkEntry" << std::endl;
		return;
	}
	std::cout << "Response: " << res << std::endl;
}
//-------------------------------------------------------------------------------------------

void HandleSubscribeRequest(NS_DM_Client::IClientAdapter* clientAdapter)
{
	std::cout << "Received Subscribe request." << std::endl;
	NS_DM_Client::NS_Common::EventEx notifyEvent;
	NS_DM_Client::NotificationUpdaterImpl* updater = new NS_DM_Client::NotificationUpdaterImpl(&notifyEvent, 5); 
	bool res = clientAdapter->SubscribeToDMSessionNotif(updater);
	if (!res)
	{
		std::cout << "Failed to SubscribeToDMSessionNotif" << std::endl;
		return;
	}
	std::cout << "Response: " << res << std::endl;
	notifyEvent.wait();
	delete updater;
}
//-------------------------------------------------------------------------------------------

void HandleDRMDReadyRequest(NS_DM_Client::IClientAdapter* clientAdapter)
{
	std::cout << "Received Subscribe request." << std::endl;
	bool res = clientAdapter->DRMDReady();
	if (!res)
	{
		std::cout << "Failed to HandleDRMDReadyRequest" << std::endl;
		return;
	}
	std::cout << "Response: " << res << std::endl;
}
//-------------------------------------------------------------------------------------------

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		std::cout << "Usage: \n" 
			<< "TestClientAdapter get DevInfo\n";
		return 0;
	}

	NS_DM_Client::IClientAdapter* clientAdapter = (NS_DM_Client::IClientAdapter*)CreateClientAdapter();
	if (clientAdapter != NULL)
	{
		bool res = clientAdapter->Open();
		if (!res)
		{
			std::cout << "Failed to open client adapter" << std::endl;
			clientAdapter->Release();
			return -1;
		}
		std::cout << "Client adapter was opened successfully" << std::endl;

		std::string requestType = argv[1];

		if (requestType == "open")
		{
			HandleOpenRequest(clientAdapter);
		}
		else if (requestType == "get")
		{
			std::string requestSubType = argv[2];
			HandleGetRequest(requestSubType, clientAdapter);
		}
		else if (requestType == "set")
		{
			std::string requestSubType = argv[2];
			HandleSetRequest(requestSubType, clientAdapter);
		}
		else if (requestType == "checkFirmware")
		{
			HandleCheckFirmwareRequest(clientAdapter);
		}
		else if (requestType == "startDMSession")
		{
			HandleStartDMSessionRequest(clientAdapter);
		}
		else if (requestType == "entry" || requestType == "netentry" || requestType == "networkentry")
		{
			int hnsp = 0;
			if (argc > 2)
			{
				hnsp = atoi(argv[2]);
			}
			const char* operName = (argc > 3) ? argv[3] : "";
			
			HandleNetworkEntry(clientAdapter, hnsp, operName);
		}
		else if (requestType == "subscribe" || requestType == "sub")
		{
			HandleSubscribeRequest(clientAdapter);
		}
		else if (requestType == "drmdready")
		{
			HandleDRMDReadyRequest(clientAdapter);
		}

	}

	clientAdapter->Close();	
	clientAdapter->Release();

	//::Sleep(1000);
	return 0;
}

