#include "MessageDeserializer.h"
#include "Message.h"
#include <Logger/LoggerMacroses.h>

const char* c_LoggerInstanceName = "MessageDeserializer";

namespace NS_DM_Client
{
    MessageDeserializer::MessageDeserializer()
    {
    }
    //-------------------------------------------------------------------------------------------

    void MessageDeserializer::operator()(void* data, size_t size, Message& message)
    {
        // !!NOTE: Implementation assumes that sizeof(MsgType) == sizeof(size_t)"
        retrieve(data, message.m_id);
        retrieve(data, (size_t&)message.m_type);
        retrieve(data, (size_t&)message.m_subType);
        retrieve(data, message.m_data);
    }
    //-------------------------------------------------------------------------------------------

    void MessageDeserializer::retrieve(void*& data, size_t& result)
    {
        memcpy(&result, data, sizeof(result));
        char* tempData = reinterpret_cast<char*>(data);
        tempData += sizeof(result);
        data = tempData;
    }
    //--------------------------------------------------------------------------------------------

    void MessageDeserializer::retrieve(void*& data, String& result)
    {
        char* tempData = reinterpret_cast<char*>(data);
        // retrieve size of string
        size_t length = 0;
        memcpy(&length, tempData, sizeof(size_t));
        // move to the string
        tempData += sizeof(size_t) / sizeof(char);
        if (length)
        {
            char* tempResult = new char[(length + 1)*sizeof(char)];
            if(tempResult == NULL)
            {
                LOG_ERROR_(NS_Logging::GetLogger(c_LoggerInstanceName), "new tempResult");
                return;
            }
            memset(tempResult, 0, (length + 1)* sizeof(char));
            memcpy(tempResult, tempData, length * sizeof(char));
            result = tempResult;
            if(tempResult != NULL) delete [] tempResult;
        }
        // skip read field
        data = tempData + length;
    }
    //--------------------------------------------------------------------------------------------

    void MessageDeserializer::retrieve(void*& data, std::vector<byte>& result)
    {
        char* tempData = reinterpret_cast<char*>(data);
        // retrieve size of string
        size_t length = 0;
        memcpy(&length, tempData, sizeof(size_t));
        // move to the string
        tempData += sizeof(size_t) / sizeof(char);
        if (length)
        {
            result.resize(length, (byte)0);
            memcpy(&result[0], tempData, length * sizeof(char));
        }
        // skip read field
        data = tempData + length;
    }
    //--------------------------------------------------------------------------------------------

    const String S_seperator("*");

    void Retrieve(const String& data, size_t& curPos, String& value)
    {
        size_t seperatorPos = data.find(S_seperator, curPos);
        String strSize = data.substr(curPos, seperatorPos - curPos);
        size_t size = atoi(strSize.c_str());
        curPos = seperatorPos + S_seperator.size();
        value = data.substr(curPos, size);
        curPos += size;
    }
    //-------------------------------------------------------------------------------------------

    void Retrieve(const String& data, size_t& curPos, int& value)
    {
        /* cxs start */
        size_t seperatorPos = data.find(S_seperator, curPos);
        /* Case Separator not found --> last value */
        if (seperatorPos==String::npos) {
            seperatorPos = data.size();
        }
        String strValue = data.substr(curPos, seperatorPos - curPos);
        value = atoi(strValue.c_str());
        curPos = seperatorPos + S_seperator.size();
        /* cxs end */
    }
    //-------------------------------------------------------------------------------------------

    void DeserializeOperatorProfile(const String& data, String& name, String& type, String& description)
    {
        size_t curPos = 0;
        Retrieve(data, curPos, name);
        Retrieve(data, curPos, type);
        Retrieve(data, curPos, description);
    }
    //-------------------------------------------------------------------------------------------

    void DeserializeConfirmationResponse(const String& data, String& messageRequest, size_t& confCode)
    {
        size_t curPos = 0;
        Retrieve(data, curPos, messageRequest);
        Retrieve(data, curPos, (int&)confCode);
    }
    //-------------------------------------------------------------------------------------------

    void DeserializeDMSessionNotification(const String& data, EventType& eventType, Initiator& initiator, NotificationStatus& statusCode)
    {
        size_t curPos = 0;
        Retrieve(data, curPos, (int&)eventType);
        Retrieve(data, curPos, (int&)initiator);
        Retrieve(data, curPos, (int&)statusCode);
    }
    //-------------------------------------------------------------------------------------------

    void DeserializeFirmwareInfo(const String& data, String& localpath, String& filename, int& size)
    {
        size_t curPos = 0;
        Retrieve(data, curPos, localpath);
        Retrieve(data, curPos, filename);
        Retrieve(data, curPos, size);
    }
    //-------------------------------------------------------------------------------------------

    void DeserializePasswords(const String& data, String& oldPassword, String& newPassword)
    {
        size_t curPos = 0;
        Retrieve(data, curPos, oldPassword);
        Retrieve(data, curPos, newPassword);
    }

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

    void DeserializePasswordsAndServerID(const String& data, String& serverID, String& oldPassword, String& newPassword)
    {
        size_t curPos = 0;
        Retrieve(data, curPos, serverID);
        Retrieve(data, curPos, oldPassword);
        Retrieve(data, curPos, newPassword);
    }

}
