/*
 * Copyright 2009 Funambol, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */

#include "daemon/ProfileComponentsHolder.h"
#include "executionqueue/ICommandDispatcher.h"
#include "executionqueue/IExecutionQueue.h"
#include "Logger/LoggerMacroses.h"
#include "treemanager/ActionCommand.h"
#include "treemanager/IResultCollector.h"
#include "treemanager/MOTreeResponseCommand.h"

static const char * const c_LogName = "ActionCommand";

#define LOG_INFO_ NS_Logging::FunctionNameLogHelper(__FUNCTION__, NS_Logging::e_info).Log

using namespace NS_DM_Client;

ActionCommand::ActionCommand(ProfileComponentsHolder* prholder, AbstractCommandPtr cmd,
        const String& msgID, const char* serverID) :
    m_command(cmd),
    m_messageID(msgID),
    m_needResponse(true),
    m_pResCollector(NULL),
    m_pProfile(prholder),
    m_resCode(e_CommandFailed),
    m_serverID(NULL)
{
    if(cmd.get() == NULL)
    {
        GDLWARN("cmd is NULL");
    }

    if (serverID)
        m_serverID = Funambol::stringdup(serverID);

    m_needResponse = (m_serverID != NULL);
}


ActionCommand::~ActionCommand()
{
    SAFE_DELETE_ARR(m_serverID);
}


MOTreeResponseCommand * ActionCommand::CreateResponse()
{
GDLDEBUG("ENTER");

    MOTreeResponseCommand *pResponse =
        new(std::nothrow) MOTreeResponseCommand(*m_pProfile->GetServerExchangeManager(), m_command, m_resCode, m_messageID, m_serverID);
    if(pResponse == (MOTreeResponseCommand*)NULL)
    {
        GDLWARN("new AlertResponseCommand");
    }

    if (m_pCommandsSink)
        pResponse->SetCommandsSink(*m_pCommandsSink);

GDLDEBUG("LEAVE");

    return pResponse;
}


bool ActionCommand::InvokeResult()
{
GDLDEBUG("ENTER");

    if (m_needResponse && m_command.get())
    {
        if (m_pResCollector)
        {
            m_pResCollector->PutResult(m_command.get(), m_resCode);
        }
        else
        {
            MOTreeResponseCommand *response = CreateResponse();
            if (!m_pProfile->GetExecutionQueue()->Add(*response))
            {
                delete response;
                return false;
            }
        }
    }
GDLDEBUG("LEAVE");

    return true;
}


void ActionCommand::SetCommandsSink(NS_SyncMLCommand::ICommandsSink &sink)
{
    m_pCommandsSink = &sink;
}

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

bool ActionCommand::notifyProvisionUpdate(CommandType commandType, EventType eventType, StatusCode result)
{
GDLDEBUG("ENTER");

    bool res = true;

    if (m_pProfile)
    {
        INotification* notification_center = m_pProfile->GetNotificationCenter();
        if (notification_center)
        {
            Funambol::ArrayList* items = getListOfItems();
            if (items)
            {
                Funambol::Item* item = 0;
                int count = items->size();

                StringArray URIs;

                for (int i = 0; i < count; ++i)
                {
                    if ((item = static_cast<Funambol::Item*> ((*items)[i])) != 0)
                    {
                        URIs.push_back(item->getTarget()->getLocURI());
                    }
                    else
                    {
                        res = false;
                        GDLERROR("casting to Funambol::Item failed");
                        break;
                    }
                }

                notification_center->ProvisioningUpdate(URIs, commandType, eventType, result);
            }
            else
            {
            	GDLERROR("can't get list of command items");
                res = false;
            }
        }
        else
        {
            GDLERROR("can't get instance of NotificationCenter");
            res = false;
        }
    }
    else
    {
        GDLERROR("component holder not valid");
        res = false;
    }

GDLDEBUG("LEAVE");

    return res;
}

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

Funambol::ArrayList* ActionCommand::getListOfItems()
{
    // for ActionCommand return 0, detailed command must return valid pointer
    return 0;
}
