#include <boost/test/unit_test.hpp>
#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"

#include <iostream>
#include "treemanager/MOTreeManager.h"
#include "../../UTestMOTree/MockDataStorage.h"

#include "Mocks/NotificationCenterMock.h"

#include "serverexchange/wrappers/SCommandAdapter.h"
#include "treemanager/MOTreeAddCommand.h"
#include "treemanager/MOTreeReplaceCommand.h"

#include <syncml/core/Item.h>
#include <syncml/core/Add.h>
#include <syncml/core/Replace.h>

#include "Common.h"
#include "Errors.h"

//------------------------------------------------------------------------------------------------------
using namespace NS_DM_Client;
//------------------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(MOTreeReplaceCommand_ReplaceWithOneItem_success)
{
    NS_DM_Client::NotificationCenterMock* notify_center =
        dynamic_cast<NS_DM_Client::NotificationCenterMock*>(S_ProfileHolder->GetNotificationCenter());
    notify_center->clearMockData();

    Funambol::ArrayList* items =  new Funambol::ArrayList;

    // create leaf node first
    // creation
    Funambol::Add* add_command = new Funambol::Add;
    // first item
    Funambol::Item* item1 = new Funambol::Item;
    Funambol::Target* target1 = new Funambol::Target("./MOTreeReplaceCommand_ReplaceWithOneItem_success/Item1");
    item1->setTarget(target1);
    Funambol::ComplexData data1("MOTreeReplaceCommand_ReplaceWithOneItem_success_Item1");
    item1->setData(&data1);
    items->add(*item1);
    // second item
    Funambol::Item* item2 = new Funambol::Item;
    Funambol::Target* target2 = new Funambol::Target("./MOTreeReplaceCommand_ReplaceWithOneItem_success/Item2");
    item2->setTarget(target2);
    Funambol::ComplexData data2("MOTreeReplaceCommand_ReplaceWithOneItem_success_item2");
    item2->setData(&data2);
    items->add(*item2);

    // main execution
    add_command->setItems(items);
    AddPtr add_ptr(add_command);
    MOTreeAddCommand tree_add_command(S_ProfileHolder, add_ptr, "1", 0);
    BOOST_CHECK(tree_add_command.Execute() == true);

    // now we can check copy command
    notify_center->clearMockData();
    items->clear();

    // third item for replace
    Funambol::Item* item3 = new Funambol::Item;
    Funambol::Source* source3 = new Funambol::Source("./MOTreeReplaceCommand_ReplaceWithOneItem_success/Item1");
    item3->setSource(source3);
    Funambol::Target* target3 = new Funambol::Target("./MOTreeReplaceCommand_ReplaceWithOneItem_success/Item2");
    item3->setTarget(target3);
    Funambol::ComplexData data3("MOTreeReplaceCommand_ReplaceWithOneItem_success_item2");
    item3->setData(&data3);
    items->add(*item3);

    Funambol::Replace* replace_command = new Funambol::Replace;
    replace_command->setItems(items);
    ReplacePtr replace_ptr(replace_command);
    MOTreeReplaceCommand tree_replace_command(S_ProfileHolder, replace_ptr, "1", 0);
    BOOST_CHECK(tree_replace_command.Execute() == true);

    // check notifications
    BOOST_CHECK(notify_center->m_mockData.size() == 2); // must be notifications: start and finish
    if (notify_center->m_mockData.size() == 2)
    {
        BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeReplaceCommand_ReplaceWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Replace);
        BOOST_CHECK(notify_center->m_mockData[0].m_event == NS_DM_Client::e_sessionStart);
        BOOST_CHECK(notify_center->m_mockData[0].m_resultCode == NS_DM_Client::e_Ok);

        BOOST_CHECK(notify_center->m_mockData[1].m_URI.compare("./MOTreeReplaceCommand_ReplaceWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Replace);
        BOOST_CHECK(notify_center->m_mockData[1].m_event == NS_DM_Client::e_sessionEnd);
        BOOST_CHECK(notify_center->m_mockData[1].m_resultCode == NS_DM_Client::e_Ok);
    }

    delete target3;
    delete source3;
    delete item3;
    delete target2;
    delete item2;
    delete target1;
    delete item1;

    delete items;
}
