/*
 * 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".
 */

/* $Id$ */

#include "DaemonDM/Messenger.h"
#include "MessengerDefs.h"
#include "IFIFOWrapper.h"
#include "lock.h"
#include "Logger/Logger.h"

namespace NS_DM_Client
{

const char* const c_MessengerLog = "Messenger";

//------------------------------------------------------------------------------------------------------
StatusCode Messenger::Init()
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::Init");

    m_fifo_request = 0;
    m_fifo_response = 0;

    m_fifo_request = CreateFIFOWrapper(false);
    if (!m_fifo_request)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "can't create fifo request wrapper");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Init, Return status: %d", e_Failed);
        return e_Failed;
    }

    StatusCode initRes = m_fifo_request->Open(c_messageRequestFifoName, false, false, true);
    if (initRes != e_Ok)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "can't open request fifo");
        m_fifo_request->Release();
        m_fifo_request = 0;
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Init, Return status: %d", initRes);
        return initRes;
    }

    m_fifo_response = CreateFIFOWrapper(false);
    if (!m_fifo_response)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "can't create fifo responce wrapper");
        m_fifo_request->Release();
        m_fifo_request = 0;
        m_fifo_response->Release();
        m_fifo_response = 0;
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Init, Return status: %d", e_Failed);
        return e_Failed;
    }

    initRes = m_fifo_response->Open(c_messageResponseFifoName, true, false, true);
    if (initRes != e_Ok)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "can't open response fifo");
        m_fifo_request->Release();
        m_fifo_request = 0;
        m_fifo_response->Release();
        m_fifo_response = 0;
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Init, Return status: %d", initRes);
        return initRes;
    }

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Init, Return status: %d", e_Ok);
    return e_Ok;
}
//------------------------------------------------------------------------------------------------------
bool Messenger::Release()
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::Release");

    if (m_fifo_request)
    {
        m_fifo_request->Release();
    }
    if (m_fifo_response)
    {
        m_fifo_response->Release();
    }

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Release, Return status: %d", true);
    return true;
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::Display(const String& message, const UIOptionalParameters& parameters)
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::Display. Message = %s", message.c_str());

    String pars_payload;
    if (!formPayloadFromOptPars(parameters, pars_payload))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "optional parameters analyse failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Display, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* reqest_payload;
    size_t reqest_payload_size;
    if (!formComplexRequestPayload(message, pars_payload, "", "", reqest_payload, reqest_payload_size))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request payload failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Display, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* request;
    size_t request_size;
    bool form_request = formComplexRequest(e_Display, reqest_payload, reqest_payload_size, request, request_size);
    deleteMemory(reqest_payload);
    if (!form_request)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Display, Return status: %d", e_Failed);
        return e_Failed;
    }

    {   // start critical section
        NS_Common::Lock lock(m_critical_section);
        if (m_fifo_request->Write(request, request_size) == e_Ok)
        {
            StatusCode res_display = ReadDisplay(parameters);
            LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Display, Return status: %d", res_display);
            deleteMemory(request);
            return res_display;
        }
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "write request to message listener failed");
            LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Display, Return status: %d, reason: write to request fifo failed", e_OperationCancelled);
            deleteMemory(request);
            return e_OperationCancelled;
        }
    }   // stop critical section

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Display, Return status: %d", e_Failed);
    return e_Failed;
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::Confirmation(const String& message, const UIOptionalParameters& parameters)
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::Confirmation. Message = %s", message.c_str());
    String pars_payload;
    if (!formPayloadFromOptPars(parameters, pars_payload))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "optional parameters analyse failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Confirmation, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* reqest_payload;
    size_t reqest_payload_size;
    if (!formComplexRequestPayload(message, pars_payload, "", "", reqest_payload, reqest_payload_size))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request payload failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Confirmation, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* request;
    size_t request_size;
    bool form_request = formComplexRequest(e_Confirmation, reqest_payload, reqest_payload_size, request, request_size);
    deleteMemory(reqest_payload);
    if (!form_request)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Confirmation, Return status: %d", e_Failed);
        return e_Failed;
    }

    {   // start critical section
        NS_Common::Lock lock(m_critical_section);
        if (m_fifo_request->Write(request, request_size) == e_Ok)
        {
            StatusCode confirmation_res = ReadConfirmation(parameters);
            LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Confirmation, Return status: %d", confirmation_res);
            deleteMemory(request);
            return confirmation_res;
        }
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "write request to message listener failed");
            LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Confirmation, Return status: %d, reason: write to request fifo failed", e_OperationCancelled);
            deleteMemory(request);
            return e_OperationCancelled;
        }
    }   // stop critical section

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::Confirmation, Return status: %d", e_Failed);
    return e_Failed;
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::UserInput(const String& message, const UIOptionalParameters& parameters, String& input)
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::UserInput. Message = %s", message.c_str());
    String pars_payload;
    if (!formPayloadFromOptPars(parameters, pars_payload))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "optional parameters analyse failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserInput, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* reqest_payload;
    size_t reqest_payload_size;
    if (!formComplexRequestPayload(message, pars_payload, "", "", reqest_payload, reqest_payload_size))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request payload failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserInput, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* request;
    size_t request_size;
    bool form_request = formComplexRequest(e_UserInput, reqest_payload, reqest_payload_size, request, request_size);
    deleteMemory(reqest_payload);
    if (!form_request)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserInput, Return status: %d", e_Failed);
        return e_Failed;
    }

    {   // start critical section
        NS_Common::Lock lock(m_critical_section);
        if (m_fifo_request->Write(request, request_size) == e_Ok)
        {
            StatusCode input_res = ReadUserInput(parameters, input);
            LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserInput, Return status: %d, user input = %s", input_res, input.c_str());
            deleteMemory(request);
            return input_res;
        }
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "write request to message listener failed");
            LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserInput, Return status: %d, reason: faiked to write to request fifo", e_OperationCancelled);
            deleteMemory(request);
            return e_OperationCancelled;
        }
    }   // stop critical section

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserInput, Return status: %d", e_Failed);
    return e_Failed;
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::UserChoice(const String& message, const UIOptionalParameters& parameters,
    const UserAvialableChoiseSet& avialable_choise_set, UserChoiseSet& choise_set, bool allowMultipleChoise)
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::UserChoice. Message = %s", message.c_str());
    String pars_payload;
    if (!formPayloadFromOptPars(parameters, pars_payload, allowMultipleChoise))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "optional parameters analyse failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserChoice, Return status: %d", e_Failed);
        return e_Failed;
    }

    String choises;
    if (!formChoiseSet(avialable_choise_set, choises))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form string representation from choise set failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserChoice, Return status: %d", e_Failed);
        return e_Failed;
    }

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "Avialable choise set = %s, allow many choises = %d", choises.c_str(), allowMultipleChoise);

    void* reqest_payload;
    size_t reqest_payload_size;
    if (!formComplexRequestPayload(message, pars_payload, choises, "", reqest_payload, reqest_payload_size))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request payload failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserChoice, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* request;
    size_t request_size;
    bool form_request = formComplexRequest(e_UserChoice, reqest_payload, reqest_payload_size, request, request_size);
    deleteMemory(reqest_payload);
    if (!form_request)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserChoice, Return status: %d", e_Failed);
        return e_Failed;
    }

    {   // start critical section
        NS_Common::Lock lock(m_critical_section);
        if (m_fifo_request->Write(request, request_size) == e_Ok)
        {
            String choise;
            StatusCode choise_res = ReadUserChoice(parameters, choise);

            if (choise_res == e_Ok)
            {
                formNumericUserChoiseFromString(choise, choise_set);
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserChoice, Return status: %d, user choise = %s", e_Ok, choise.c_str());
                deleteMemory(request);
                return e_Ok;
            }
            else
            {
                LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "can't read user choises");
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserChoice, Return status: %d", e_OperationCancelled);
                deleteMemory(request);
                return e_OperationCancelled;
            }
        }
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "write request to message listener failed");
            LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserChoice, Return status: %d, reason: failed to write to request fifo", e_OperationCancelled);
            deleteMemory(request);
            return e_OperationCancelled;
        }
    }   // stop critical section

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::UserChoice, Return status: %d", e_Failed);
    return e_Failed;
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::ProgressNotification(const String& message, const UIOptionalParameters& parameters,
    long size_to_download)
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::ProgressNotification. Message = %s", message.c_str());

    String pars_payload;
    if (!formPayloadFromOptPars(parameters, pars_payload))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "optional parameters analyse failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ProgressNotification, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* reqest_payload;
    size_t reqest_payload_size;

    char chr_progress[16];

	#if defined PLATFORM_WINDOWS
		sprintf_s(chr_progress, "%ld", size_to_download);
	#else
		sprintf(chr_progress, "%ld", size_to_download);
	#endif

	String progress = chr_progress;
    if (!formComplexRequestPayload(message, pars_payload, "", progress, reqest_payload, reqest_payload_size))
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request payload failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ProgressNotification, Return status: %d", e_Failed);
        return e_Failed;
    }

    void* request;
    size_t request_size;
    bool form_request = formComplexRequest(e_ProgressNotification, reqest_payload, reqest_payload_size, request, request_size);
    deleteMemory(reqest_payload);
    if (!form_request)
    {
        LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "form request failed");
        LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ProgressNotification, Return status: %d", e_Failed);
        return e_Failed;
    }

    {   // start critical section
        NS_Common::Lock lock(m_critical_section);
        if (m_fifo_request->Write(request, request_size) == e_Ok)
        {
            if (ReadProgressNotification(parameters) == e_Ok)
            {
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ProgressNotification, Return status: %d", e_Ok);
                deleteMemory(request);
                return e_Ok;
            }
            else
            {
                LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "can't read user choises");
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ProgressNotification, Return status: %d, reason: failed read progress notification", e_OperationCancelled);
                deleteMemory(request);
                return e_OperationCancelled;
            }
        }   // stop critical section
        else
        {
            LOG_ERROR_(NS_Logging::GetLogger(c_MessengerLog), "%s", "write request to message listener failed");
            LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ProgressNotification, Return status: %d, reason: failed to write to request fifo", e_OperationCancelled);
            deleteMemory(request);
            return e_OperationCancelled;
        }
    }

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ProgressNotification, Return status: %d", e_Failed);
    return e_Failed;
}
//------------------------------------------------------------------------------------------------------
Messenger::~Messenger()
{
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::ReadDisplay(const UIOptionalParameters& parameters)
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::ReadDisplay");
    Buffer response(sizeof(UIResponseExchangeHead));
    while(true)
    {
        if (m_fifo_response->Read(response, true) == e_Ok)
        {
            UIResponseExchangeHead head;
            memcpy(&head, response.GetPointer(), sizeof(UIResponseExchangeHead));
            if (head.m_perform_code == e_Ok)
            {
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadDisplay, Return status: %d", e_Ok);
                return e_Ok;
            }
            else
            {
                break;
            }
        }
        break;
    }

    LOG_WARNING_(NS_Logging::GetLogger(c_MessengerLog), "%s", "read respond from message listener failed");
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadDisplay, Return status: %d", e_OperationCancelled);
    return e_OperationCancelled;
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::ReadConfirmation(const UIOptionalParameters& parameters)
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::ReadConfirmation");
    Buffer response(sizeof(UIResponseExchangeHead));
    while(true)
    {
        if (m_fifo_response->Read(response, true) == e_Ok)
        {
            UIResponseExchangeHead head;
            memcpy(&head, response.GetPointer(), sizeof(UIResponseExchangeHead));
            if (head.m_perform_code == e_Ok)
            {
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadConfirmation, Return status: %d, it seems that user ask \'yes\'", e_Ok);
                return e_Ok;
            }
            else
            {
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadConfirmation, Return status: %d, it seems that user ask \'no\'", head.m_perform_code);
                return head.m_perform_code;
            }
        }
        else
        {
            LOG_WARNING_(NS_Logging::GetLogger(c_MessengerLog), "Failed to read from response fifo", e_Ok);
        }
        break;
    }

    LOG_WARNING_(NS_Logging::GetLogger(c_MessengerLog), "%s", "read respond from message listener failed. Try find DR optional parameter");

    for (UIOptionalParameters::const_iterator ptr = parameters.begin(); ptr != parameters.end(); ++ptr)
    {
        if (ptr->m_parameter == e_DR)
        {
            LOG_INFO_(NS_Logging::GetLogger(c_MessengerLog), "%s%s", "DR optional parameter present. Use it as conformation: ", ptr->m_data.c_str());
            if ((ptr->m_data.compare("y") == 0) || (ptr->m_data.compare("Y") == 0))
            {
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadConfirmation, Return status: %d, it seems that user ask \'yes\'", e_Ok);
                return e_Ok;
            }
            else
            {
                LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadConfirmation, Return status: %d, it seems that user ask \'no\'", e_OperationCancelled);
                return e_OperationCancelled;
            }
        }
    }

    LOG_WARNING_(NS_Logging::GetLogger(c_MessengerLog), "%s", "DR optional parameter not find. Seems that user ask \'no\'");
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadConfirmation, Return status: %d", e_OperationCancelled);
    return e_OperationCancelled;
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::ReadUserInput(const UIOptionalParameters& parameters, String& input)
{
    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "ENTER >> Messenger::ReadUserInput");
    Buffer response(sizeof(UIResponseExchangeHead));
    while(true)
    {
        if (m_fifo_response->Read(response, true) == e_Ok)
        {
            UIResponseExchangeHead head;
            memcpy(&head, response.GetPointer(), sizeof(UIResponseExchangeHead));
            if (head.m_perform_code == e_Ok)
            {
                Buffer payload(head.m_payload_size);
                if (m_fifo_response->Read(payload, true) == e_Ok)
                {
                    input = (char*)(payload.GetPointer());
                    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadUserInput, Return status: %d, user input = %s", e_Ok, input.c_str());
                    return e_Ok;
                }
                else
                {
                    LOG_WARNING_(NS_Logging::GetLogger(c_MessengerLog), "Failed to read from response fifo", e_Ok);
                    break;
                }
            }
            else
            {
                break;
            }
        }
        break;
    }

    LOG_WARNING_(NS_Logging::GetLogger(c_MessengerLog), "%s", "read respond from message listener failed");

    for (UIOptionalParameters::const_iterator ptr = parameters.begin(); ptr != parameters.end(); ++ptr)
    {
        if (ptr->m_parameter == e_DR)
        {
            input = ptr->m_data;
            LOG_INFO_(NS_Logging::GetLogger(c_MessengerLog), "%s%s", "DR optional parameter present. Use it as user input: ", input.c_str());
            return e_Ok;
        }
    }

    LOG_DEBUG_(NS_Logging::GetLogger(c_MessengerLog), "LEAVE << Messenger::ReadUserInput, Return status: %d", e_OperationCancelled);
    return e_OperationCancelled;
}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::ReadUserChoice(const UIOptionalParameters& parameters, String& choise)
{
    Buffer response(sizeof(UIResponseExchangeHead));
    while(true)
    {
        if (m_fifo_response->Read(response, true) == e_Ok)
        {
            UIResponseExchangeHead head;
            memcpy(&head, response.GetPointer(), sizeof(UIResponseExchangeHead));
            if (head.m_perform_code == e_Ok)
            {
                Buffer payload(head.m_payload_size);
                if (m_fifo_response->Read(payload, true) == e_Ok)
                {
                    choise = (char*)(payload.GetPointer());
                    return e_Ok;
                }
                else
                {
                    break;
                }
            }
            else
            {
                break;
            }
        }
        break;
    }

    LOG_WARNING_(NS_Logging::GetLogger(c_MessengerLog), "%s", "read respond from message listener failed");

    for (UIOptionalParameters::const_iterator ptr = parameters.begin(); ptr != parameters.end(); ++ptr)
    {
        if (ptr->m_parameter == e_DR)
        {
            choise = ptr->m_data;
            LOG_INFO_(NS_Logging::GetLogger(c_MessengerLog), "%s%s", "DR optional parameter present. Use it as user choise: ", choise.c_str());
            return e_Ok;
        }
    }

    return e_OperationCancelled;

}
//------------------------------------------------------------------------------------------------------
StatusCode Messenger::ReadProgressNotification(const UIOptionalParameters& parameters)
{
    Buffer response(sizeof(UIResponseExchangeHead));
    while(true)
    {
        if (m_fifo_response->Read(response, true) == e_Ok)
        {
            UIResponseExchangeHead head;
            memcpy(&head, response.GetPointer(), sizeof(UIResponseExchangeHead));
            if (head.m_perform_code == e_Ok)
            {
                return e_Ok;
            }
            else
            {
                break;
            }
        }
        break;
    }

    LOG_WARNING_(NS_Logging::GetLogger(c_MessengerLog), "%s", "read respond from message listener failed");

    return e_OperationCancelled;
}
//------------------------------------------------------------------------------------------------------

}
