/*
 * 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 "daemon/DaemonEngine.h"
#include "common/Buffer.h"
#include "base/util/StringBuffer.h"
#include "daemon/Configuration.h"
#include "daemon/Profile.h"

#include "syncml/core/Get.h"
#include "syncml/core/Item.h"
#include "syncml/core/Target.h"
#include "Logger/LoggerMacroses.h"

#include "treemanager/MOTreeGetCommandTest.h"
#include "treemanager/MOTreeGetCommand.h"

#include "treemanager/MOTreeExecCommand.h"
#include "treemanager/IMOTreeManager.h"

#include "executionqueue/IExecutionQueue.h"

#include "Event.h"

#include "Errors.h"
#include "serverexchange/commands/RequestFWUCommand.h"

using namespace NS_DM_Client;
using namespace NS_DM_Client::NS_Daemon;

static const char c_LoggerInstanceName[] = "DaemonEngine";

StatusCode DaemonEngine::execute_RequestGetValueFromTreeCommand(const Buffer& input, StatusCode& response_res, Buffer& output)
{
    StatusCode res = e_Failed;

    while (true)
    {
        // parsing input
        char* char_path = (char*)malloc(input.Size() + 1);
        if (char_path)
        {
            memcpy(char_path, input.GetPointer(), input.Size());
            char_path[input.Size()] = '\0';
        }
        else
        {
            LERROR("Failed allocate memory for tree uri");
            break;
        }

        String path = char_path;
        free(char_path);
        String profile;
        String uri;
        size_t delimiter;
        if ((delimiter = path.find(':')) != String::npos)
        {
            profile = path.substr(0, delimiter);
            uri = path.substr(delimiter + 1);
        }
        else
        {
            LERROR("Failed to find delimiter between profile and uri. Uri format incorrect");
            break;
        }

        // get appropriate profile
        ProfileComponentsHolder* prholder = 0;
        for(int i = 0; i < m_conf.GetProfilesCount(); ++i)
        {
            Profile* p = m_conf.GetProfile(i);
            String pr_name = p->GetName();
            if (p->GetName() == profile)
            {
                if (p->IsEnabled())
                {
                    prholder = p->GetComponentsHolder();
                    break;
                }
                else
                {
                    LERROR("Selected profile not enabled");
                    break;
                }
            }
        }
        if (!prholder)
        {
            LERROR("can't get appropriate profile holder");
	    break;
        }

        // creation
        Funambol::Get* get_command = new Funambol::Get;
        // initialization with URI
        Funambol::Item* item = new Funambol::Item;
        Funambol::ArrayList* items =  new Funambol::ArrayList;
        Funambol::Target* target = new Funambol::Target(uri.c_str(), 0, 0);

        if (get_command && item && items && target)
        {
            item->setTarget(target);
            items->add(*item);
            get_command->setItems(items);
            GetPtr ptr(get_command);

            Buffer result;

            NS_Common::EventEx sigResult;
            MOTreeGetCommandTest* command = new MOTreeGetCommandTest(prholder, ptr, "1", &sigResult, res, output);
            if (prholder->GetExecutionQueue()->Add(*command))
            {
                if (sigResult.wait() == MOTreeGetCommandTest::e_CommandExecuted)
                {
                    response_res = res;
                }
                else
                {
                    LWARN("command was not executed");
                }
            }
            else
            {
                delete command;
            }

            delete target;
            delete items;
            delete item;
        }
        break;
    }

	return res;
}

StatusCode DaemonEngine::execute_RequestFirmwareUpdate(bool userInitiated, const Buffer& input)
{
    StatusCode res = e_Failed;

    while (true)
    {
        // parsing input
        char* char_profile = (char*)malloc(input.Size() + 1);
        if (char_profile)
        {
            memcpy(char_profile, input.GetPointer(), input.Size());
            char_profile[input.Size()] = '\0';
        }
        else
        {
            LERROR("Failed allocate memory for profile string representation");
            break;
        }

        String profile = char_profile;
        free(char_profile);

        // get appropriate profile
        ProfileComponentsHolder* prholder = 0;
        for(int i = 0; i < m_conf.GetProfilesCount(); ++i)
        {
            Profile* p = m_conf.GetProfile(i);
            String pr_name = p->GetName();
            if (p->GetName() == profile)
            {
                if (p->IsEnabled())
                {
                    prholder = p->GetComponentsHolder();
                    break;
                }
                else
                {
                    LERROR("Selected profile not enabled");
                    break;
                }
            }
        }
        if (!prholder)
        {
            LERROR("can't get appropriate profile holder");
	        break;
        }

        LOG_DEBUG_(NS_Logging::GetLogger(c_LoggerInstanceName), "execute_RequestFirmwareUpdate: BEFORE RequestFWUCommand command creation and queue. User initiated: %s", userInitiated ? "true" : "false");
        NS_Communication::RequestFWUCommand* command = new NS_Communication::RequestFWUCommand(*prholder, userInitiated);
        if (prholder->GetExecutionQueue()->Add(*command))
        {
            LOG_DEBUG_(NS_Logging::GetLogger(c_LoggerInstanceName), "execute_RequestFirmwareUpdate: After RequestFWUCommand command creation and queue - SUCCESS");
            res = e_Ok;
        }
        else
        {
            LOG_DEBUG_(NS_Logging::GetLogger(c_LoggerInstanceName), "execute_RequestFirmwareUpdate: After RequestFWUCommand command creation and queue - FAIL");
            delete command;
        }

        break;
    }

    return res;
}

