#include "ClientAdapter/TestClientAdapter.h"
#include "ClientAdapter/ClientAdapter.h"
#include "ClientAdapter/ProvisionInfo.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 "../UTestClientAdapter/NotificationUpdaterImpl.h"
#include "StatusCallbackImpl.h"
#include "ConfirmationImpl.h"
#include "Event.h"
#include "Utils.h"
#include <algorithm>
#include "common/commontypes.h"
#include "platform.h"
#include "Logger/LoggerMacroses.h"
#include <android/log.h>

#ifdef PLATFORM_WINDOWS
    #include <fstream>
#endif

const char* const c_LogName = "TestClientAdapter";
#define printf(...) __android_log_print(ANDROID_LOG_DEBUG, "TestClientAdapter", __VA_ARGS__);

namespace NS_DM_Client
{
    TestClientAdapter::TestClientAdapter(): m_clientAdapter(0)
     {
        m_clientAdapter = (NS_DM_Client::IClientAdapter*)CreateClientAdapter();
        if (m_clientAdapter != NULL)
         {
            bool res = m_clientAdapter->Open();
            if (!res)
              {
                printf("Failed to open client adapter\n");
                GDLERROR("Failed to open client adapter");
                return;
              }
            printf("Client adapter was opened successfully\n");
            GDLINFO("Client adapter was opened successfully");
         }
        else
        {
            printf("CreateClientAdapter is failed\n");
        }
    }
    //-------------------------------------------------------------------------------------------
    TestClientAdapter::~TestClientAdapter()
     {
         if (m_clientAdapter)
            m_clientAdapter->Release();
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::GetManagementObject(const char* objectName)
     {
        printf("Received request = %s\n", objectName);
        GDLINFO("Received request = %s", objectName);
        bool res = false;
        NS_DM_Client::IMgmtObject* mgmtObject = (NS_DM_Client::IMgmtObject*)NULL;
        if (std::string(objectName) == "DevInfo")
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::DevInfo();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new DevInfo");
                return false;
            }
            res = m_clientAdapter->GetDeviceInfo(static_cast<NS_DM_Client::DevInfo&>(*mgmtObject));
         } 
        else if (std::string(objectName) == "DevDetail")
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::DevDetail();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new DevDetail");
                return false;
            }
            res = m_clientAdapter->GetDeviceDetail(static_cast<NS_DM_Client::DevDetail&>(*mgmtObject));
         }
        else if (std::string(objectName) == "DMAcc")
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::DMAcc();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new DMAcc");
                return false;
            }
            res = m_clientAdapter->GetDMAccount(static_cast<NS_DM_Client::DMAcc&>(*mgmtObject));
         }
        else if (std::string(objectName) == "WiMAXSupp")
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::WiMAXSupp();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new WiMAXSupp");
                return false;
            }
            res = m_clientAdapter->GetWiMAXSupp(static_cast<NS_DM_Client::WiMAXSupp&>(*mgmtObject));
         }
        else if (std::string(objectName) == "WiMAX")
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::WiMAX();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new WiMAX");
                return false;
            }
            res = m_clientAdapter->GetWiMAX(static_cast<NS_DM_Client::WiMAX&>(*mgmtObject));
         }

        if (!res)
         {
            printf("Failed to handle request\n");
            GDLERROR("Failed to handle request");
            return res;
         }
        String xmlResult;
        mgmtObject->Serialize(xmlResult);
        printf("Response: %s\n", xmlResult.c_str());
        GDLINFO("Response: %s", xmlResult.c_str());

#ifdef PLATFORM_WINDOWS
        std::ofstream response("Response.xml");
        response << xmlResult;
#endif

        if(mgmtObject != (NS_DM_Client::IMgmtObject*)NULL) delete mgmtObject;
        return res;
    }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::SetManagementObject(const char* objectName)
     {
        printf("Received request = %s\n", objectName);
        GDLINFO("Received request = %s", objectName);
        NS_DM_Client::IMgmtObject* mgmtObject = (NS_DM_Client::IMgmtObject*)NULL;
        bool res = false;
        if (strcmp(objectName, "DevInfo") == 0)
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::DevInfo();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new DevInfo");
                return false;
            }
            NS_DM_Client::DevInfo& deviceInfo = static_cast<NS_DM_Client::DevInfo&>(*mgmtObject);
            fillInDevInfo(deviceInfo);
            res = m_clientAdapter->SetDeviceInfo(deviceInfo);
         }
        else if (strcmp(objectName, "DevDetail") == 0)
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::DevDetail();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new DevDetail");
                return false;
            }
            NS_DM_Client::DevDetail& deviceDetail = static_cast<NS_DM_Client::DevDetail&>(*mgmtObject);
            fillInDevDetail(deviceDetail);
            res = m_clientAdapter->SetDeviceDetail(static_cast<NS_DM_Client::DevDetail&>(deviceDetail));
         }
        else if (strcmp(objectName, "DMAcc") == 0)
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::DMAcc();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new DMAcc");
                return false;
            }
            res = m_clientAdapter->SetDMAccount(static_cast<NS_DM_Client::DMAcc&>(*mgmtObject));
         }
        else if (strcmp(objectName, "WiMAXSupp") == 0)
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::WiMAXSupp();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new WiMAXSupp");
                return false;
            }
            NS_DM_Client::WiMAXSupp& wimaxSupp = static_cast<NS_DM_Client::WiMAXSupp&>(*mgmtObject);
            fillInWiMAXSupp(wimaxSupp);
            res = m_clientAdapter->SetWiMAXSupp(wimaxSupp);
         }
        else if (strcmp(objectName, "WiMAX") == 0)
         {
            mgmtObject = new(std::nothrow) NS_DM_Client::WiMAX();
            if(mgmtObject == (NS_DM_Client::IMgmtObject*)NULL)
            {
                printf("Error: new WiMAX");
                return false;
            }
            res = m_clientAdapter->SetWiMAX(static_cast<NS_DM_Client::WiMAX&>(*mgmtObject));
         }

        if(mgmtObject != (NS_DM_Client::IMgmtObject*)NULL) delete mgmtObject;

        printf("Response: %d\n", res);
        return res;
    }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::SetEMSK(const char* emsk)
     {
        return m_clientAdapter->SetEMSK(emsk, strlen(emsk));
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::GetProfileActivationStatus(bool& isActive)
     {
        return m_clientAdapter->GetProfileActivationStatus(isActive);
     }
    //-------------------------------------------------------------------------------------------

    bool TestClientAdapter::SetManufacturer(const char* manufacturer)
     {
        return m_clientAdapter->SetManufacturer(manufacturer, strlen(manufacturer));
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::SetModel(const char* model)
     {
        return m_clientAdapter->SetModel(model, strlen(model));
     }
    //-------------------------------------------------------------------------------------------

    bool TestClientAdapter::SetDeviceID(const char* deviceID)
     {
        return m_clientAdapter->SetDeviceID(deviceID, strlen(deviceID));
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::SetWiMAXDiagnostics()
     {
        NS_DM_Diagnostics::WiMAX_Diagnostics* wimaxDiagnostics = new(std::nothrow) NS_DM_Diagnostics::WiMAX_Diagnostics();
        if(wimaxDiagnostics == (NS_DM_Diagnostics::WiMAX_Diagnostics*)NULL)
        {
            printf("Error: new WiMAX_Diagnostics");
            return false;
        }
        fillInWiMAXDiagnostics(*wimaxDiagnostics);
        bool res = m_clientAdapter->SetWiMAXDiagnostics(*wimaxDiagnostics);
        if(wimaxDiagnostics != (NS_DM_Diagnostics::WiMAX_Diagnostics*)NULL) delete wimaxDiagnostics;
        return res;
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::GetManagementTree(const char* uri)
     {
        String mgmtTree;
        bool res = m_clientAdapter->GetMgmtTree(uri, mgmtTree);
        if (!res)
         {
            printf("Failed to handle request GetMgmtTree with uri = %s\n", uri);
            GDLERROR("Failed to handle request GetMgmtTree with uri = %s", uri);
            return res;
         }
        printf("Response MgmtTree: \n%s\n", mgmtTree.c_str());
        GDLINFO("Response MgmtTree: \n%s", mgmtTree.c_str());

#ifdef PLATFORM_WINDOWS
        std::ofstream response("Response.xml");
        response << mgmtTree;
#endif
        return res;
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::Set(const char* filename)
     {
        String mgmtTree;
        ReadFromFile(filename, mgmtTree);
        //DWORD start = ::GetTickCount();
        bool res = m_clientAdapter->SetMgmtTree(mgmtTree);
        if (!res)
         {
            printf("Failed to handle request\n");
            GDLINFO("Failed to handle request");
            return res;
         }
        //DWORD finish = ::GetTickCount();
        //DWORD duration = finish - start;
        //std::cout << "PERFOMANCE: SetMgmtTree, duration (millisec) = " << duration << std::endl;
        return res;
    }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::GetClientProfiles()
     {
        std::vector<NS_DM_Client::ClientProfileInfo> profiles;
        bool res = m_clientAdapter->GetClientProfiles(profiles);
        printf("Profile's count = %d\n", profiles.size());
        GDLINFO("Profile's count = %d", profiles.size());
        for (int i = 0; i != profiles.size(); ++i)
        {
            printf("Profile %d, Name = %s, Type = %s, Description = %s\n", i, profiles[i].m_name.c_str(), profiles[i].m_type.c_str(),
                profiles[i].m_description.c_str());
            GDLINFO("Profile %d, Name = %s, Type = %s, Description = %s", i, profiles[i].m_name.c_str(), profiles[i].m_type.c_str(),
                profiles[i].m_description.c_str());
        }
        return true;
    }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::CheckFirmware()
     {
        printf("Received CheckFirmware request\n");
        GDLINFO("Received CheckFirmware request");
        NS_DM_Client::NS_Common::EventEx notifyEvent;
        NS_DM_Client::IStatusCallback* callback = new(std::nothrow) StatusCallbackImpl(&notifyEvent);
        if(callback == (NS_DM_Client::IStatusCallback*)NULL)
        {
            printf("Error: new StatusCallbackImpl");
            return false;
        }
        bool res = m_clientAdapter->CheckForFirmwareUpdate(callback);
        if (!res)
         {
            printf("Failed to CheckForFirmwareUpdate\n");
            GDLERROR("Failed to CheckForFirmwareUpdate");
            if(callback != (NS_DM_Client::IStatusCallback*)NULL) delete callback;
            return res;
         }
        printf("Response: %d\n", res);
        GDLINFO("Response: %d", res);
        notifyEvent.wait();
        if(callback != (NS_DM_Client::IStatusCallback*)NULL) delete callback;
        return res;
    }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::HandleProvision()
     {
        printf("Received ProvisionRequest request\n");
        GDLINFO("Received ProvisionRequest request");
        NS_DM_Client::NS_Common::EventEx notifyEvent;
        NS_DM_Client::NotificationUpdaterImpl* updater = new(std::nothrow) NS_DM_Client::NotificationUpdaterImpl(&notifyEvent);
        if(updater == (NS_DM_Client::NotificationUpdaterImpl*)NULL)
        {
            printf("Error: new NotificationUpdaterImpl");
            return false;
        }
        NS_DM_Client::ProvisionInfoRequest provision;
        provision.m_URI = "./WiMAX1";
        provision.m_commands = 2;
        provision.m_events = 6;
        provision.m_monitorChildren = false;
        bool res = m_clientAdapter->SubscribeToNotification(provision, updater);
        if (!res)
         {
            printf("Failed to CheckForFirmwareUpdate\n");
            GDLERROR("Failed to CheckForFirmwareUpdate");
            if(updater != (NS_DM_Client::NotificationUpdaterImpl*)NULL) delete updater;
            return res;
         }
        printf("Response: %d\n", res);
        GDLINFO("Response: %d", res);
        notifyEvent.wait();

        res = m_clientAdapter->UnsubscribeToProvisioningUpdateNotif();
        printf("Response: %d\n", res);
        GDLINFO("Response: %d", res);
        if(updater != (NS_DM_Client::NotificationUpdaterImpl*)NULL) delete updater;
        return res;
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::HandleConfirmation()
     {
        printf("Received ConfirmationRequest request\n");
        GDLINFO("Received ConfirmationRequest request");
        NS_DM_Client::NS_Common::EventEx notifyEvent;
        NS_DM_Client::IConfirmation* confirmation = new(std::nothrow) ConfirmationImpl(*m_clientAdapter, &notifyEvent);
        if(confirmation == (NS_DM_Client::IConfirmation*)NULL)
        {
            printf("Error: new ConfirmationImpl");
            return false;
        }
        bool res = m_clientAdapter->SubscribeToConfirmation(confirmation);
        if (!res)
         {
            printf("Failed to SubscribeToConfirmation\n");
            GDLERROR("Failed to SubscribeToConfirmation");
            if(confirmation != (NS_DM_Client::IConfirmation*)NULL) delete confirmation;
            return res;
         }
        printf("Response: %d\n", res);
        GDLINFO("Response: %d", res);
        notifyEvent.wait();
        if(confirmation != (NS_DM_Client::IConfirmation*)NULL) delete confirmation;
        return res;
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::StartDMSession(const char *alertType)
     {
        printf("Received startDMSession request %s\n", alertType ? alertType : "");
        GDLINFO("Received startDMSession request %s", alertType ? alertType : "");
        NS_DM_Client::NS_Common::EventEx notifyEvent;
        NS_DM_Client::IStatusCallback* callback = new(std::nothrow) StatusCallbackImpl(&notifyEvent);
        if(callback == (NS_DM_Client::IStatusCallback*)NULL)
        {
            printf("Error: new StatusCallbackImpl");
            return false;
        }
        bool res = m_clientAdapter->StartDMSession(alertType ? alertType : "AlertMessage", callback);
        if (!res)
         {
            printf("Failed to StartDMSession\n");
            GDLERROR("Failed to StartDMSession");
            if(callback != (NS_DM_Client::IStatusCallback*)NULL) delete callback;
            return res;
         }
        printf("Response: %d\n", res);
        GDLINFO("Response: %d", res);
        notifyEvent.wait();
        if(callback != (NS_DM_Client::IStatusCallback*)NULL) delete callback;
        return res;
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::HandleNetworkEntry(int hnspID, const char* operatorName)
     {
        printf("Received NetworkEntry request\n");
        GDLINFO("Received NetworkEntry request");
        bool res = m_clientAdapter->HandleNetworkEntry(hnspID, operatorName);
        if (!res)
         {
            printf("Failed to HandleNetworkEntry\n");
            GDLERROR("Failed to HandleNetworkEntry");
         }
        return res;
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::Subscribe()
     {
        printf("Received Subscribe request\n");
        GDLINFO("Received Subscribe request");
        NS_DM_Client::NS_Common::EventEx notifyEvent;
        NS_DM_Client::NotificationUpdaterImpl* updater = new(std::nothrow) NS_DM_Client::NotificationUpdaterImpl(&notifyEvent, 5);
        if(updater == (NS_DM_Client::NotificationUpdaterImpl*)NULL)
        {
            printf("Error: new NotificationUpdaterImpl");
            return false;
        }
        bool res = m_clientAdapter->SubscribeToDMSessionNotification(updater);
        if (!res)
         {
            printf("Failed to SubscribeToDMSessionNotif\n");
            GDLERROR("Failed to SubscribeToDMSessionNotif");
            if(updater != (NS_DM_Client::NotificationUpdaterImpl*)NULL) delete updater;
            return res;
         }
        printf("Response: %d\n", res);
        GDLINFO("Response: %d", res);
        notifyEvent.wait();
        if(updater != (NS_DM_Client::NotificationUpdaterImpl*)NULL) delete updater;
        return res;
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::DRMDReadyRequest()
     {
        printf("Received Subscribe request\n");
        GDLINFO("Received Subscribe request");
        bool res = m_clientAdapter->DRMDReady();
        if (!res){
            printf("Failed to HandleDRMDReadyRequest\n");
            GDLERROR("Failed to HandleDRMDReadyRequest");
         }
        return res;
     }
    //-------------------------------------------------------------------------------------------
    void TestClientAdapter::fillInDevInfo(DevInfo& deviceInfo)
     {
        deviceInfo.m_DevId = "DevId";
        deviceInfo.m_Man = "Man";
        deviceInfo.m_Mod = "Mod";
        deviceInfo.m_DmV = "DmV";
        deviceInfo.m_Lang = "Lang";
     }
    //-------------------------------------------------------------------------------------------
    void TestClientAdapter::fillInDevDetail(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 TestClientAdapter::fillInWiMAXSupp(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);

        String name1("SomeOperator1");
        String name2("SomeOperator2");
        wimaxSupp.m_Operator[name1] = oper;
        wimaxSupp.m_Operator[name2] = oper;
    }
    //-------------------------------------------------------------------------------------------
    void TestClientAdapter::fillInWiMAXDiagnostics(NS_DM_Diagnostics::WiMAX_Diagnostics& wimaxDiagnostics)
     {
        wimaxDiagnostics.Execute();
     }
    //-------------------------------------------------------------------------------------------
    bool TestClientAdapter::StartBootstrap()
     {
        printf("Received StartBootstrap request\n");
        GDLINFO("Received StartBootstrap request");
        bool res = m_clientAdapter->StartBootstrapRequest();
        if (!res)
         {
            printf("Failed to StartBootstrap\n");
            GDLERROR("Failed to StartBootstrap");
         }
        return res;
     }
}

