#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/MOTreeCopyCommand.h"

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

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

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

BOOST_AUTO_TEST_CASE(MOTreeCopyCommand_CopyWithOneItem_success)
{
    // first add two leaf nodes for using it when copy

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

    // creation
    Funambol::Add* add_command = new Funambol::Add;
    Funambol::ArrayList* items =  new Funambol::ArrayList;
    // first item
    Funambol::Item* item1 = new Funambol::Item;
    Funambol::Target* target1 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item1");
    item1->setTarget(target1);
    Funambol::ComplexData data1("MOTreeCopyCommand_CopyWithOneItem_success_Item1");
    item1->setData(&data1);
    items->add(*item1);
    // second item
    Funambol::Item* item2 = new Funambol::Item;
    Funambol::Target* target2 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item2");
    item2->setTarget(target2);
    Funambol::ComplexData data2("MOTreeCopyCommand_CopyWithOneItem_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 copy
    Funambol::Item* item3 = new Funambol::Item;
    Funambol::Source* source3 = new Funambol::Source("./MOTreeCopyCommand_CopyWithOneItem_success/Item1");
    item3->setSource(source3);
    Funambol::Target* target3 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item2");
    item3->setTarget(target3);
    Funambol::ComplexData data3("MOTreeCopyCommand_CopyWithOneItem_success_item2");
    item3->setData(&data3);
    items->add(*item3);

    Funambol::Copy* copy_command = new Funambol::Copy;
    copy_command->setItems(items);
    CopyPtr copy_ptr(copy_command);
    MOTreeCopyCommand tree_copy_command(S_ProfileHolder, copy_ptr, "1", 0);
    BOOST_CHECK(tree_copy_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("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Copy);
        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("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Copy);
        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;
}

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

    // creation
    Funambol::Copy* copy_command = new Funambol::Copy;
    Funambol::ArrayList* items =  new Funambol::ArrayList;

    // item for copy
    Funambol::Item* item = new Funambol::Item;
    Funambol::Source* source = new Funambol::Source("./MOTreeCopyCommand_CopyWithOneItem_failed/Item1"); // not existing item
    item->setSource(source);
    Funambol::Target* target = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_failed/Item2"); // not existing item
    item->setTarget(target);
    Funambol::ComplexData data("MOTreeCopyCommand_CopyWithOneItem_success_item2");
    item->setData(&data);
    items->add(*item);

    copy_command->setItems(items);
    CopyPtr copy_ptr(copy_command);
    MOTreeCopyCommand tree_copy_command(S_ProfileHolder, copy_ptr, "1", 0);
    BOOST_CHECK(tree_copy_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("./MOTreeCopyCommand_CopyWithOneItem_failed/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Copy);
        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("./MOTreeCopyCommand_CopyWithOneItem_failed/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Copy);
        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 target;
    delete source;
    delete item;

    delete items;

}

BOOST_AUTO_TEST_CASE(MOTreeCopyCommand_CopyWithManyItem_success)
{
    // first add two leaf nodes for using it when copy

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

    // creation
    Funambol::Add* add_command = new Funambol::Add;
    Funambol::ArrayList* items =  new Funambol::ArrayList;
    // first item
    Funambol::Item* item1 = new Funambol::Item;
    Funambol::Target* target1 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item1");
    item1->setTarget(target1);
    Funambol::ComplexData data1("MOTreeCopyCommand_CopyWithOneItem_success_Item1");
    item1->setData(&data1);
    items->add(*item1);
    // second item
    Funambol::Item* item2 = new Funambol::Item;
    Funambol::Target* target2 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item2");
    item2->setTarget(target2);
    Funambol::ComplexData data2("MOTreeCopyCommand_CopyWithOneItem_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 copy
    Funambol::Item* item3 = new Funambol::Item;
    Funambol::Source* source3 = new Funambol::Source("./MOTreeCopyCommand_CopyWithOneItem_success/Item1");
    item3->setSource(source3);
    Funambol::Target* target3 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item2");
    item3->setTarget(target3);
    Funambol::ComplexData data3("MOTreeCopyCommand_CopyWithOneItem_success_item2");
    item3->setData(&data3);

    items->add(*item3); // add three item
    items->add(*item3);
    items->add(*item3);


    Funambol::Copy* copy_command = new Funambol::Copy;
    copy_command->setItems(items);
    CopyPtr copy_ptr(copy_command);
    MOTreeCopyCommand tree_copy_command(S_ProfileHolder, copy_ptr, "1", 0);

    BOOST_CHECK(tree_copy_command.Execute() == true);


    // check notifications
    BOOST_CHECK(notify_center->m_mockData.size() == 6); // must be notifications: start and finish
    if (notify_center->m_mockData.size() == 6)
    {
        BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Copy);
        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("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Copy);
        BOOST_CHECK(notify_center->m_mockData[1].m_event == NS_DM_Client::e_sessionStart);
        BOOST_CHECK(notify_center->m_mockData[1].m_resultCode == NS_DM_Client::e_Ok);

        BOOST_CHECK(notify_center->m_mockData[2].m_URI.compare("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[2].m_command == NS_DM_Client::e_Copy);
        BOOST_CHECK(notify_center->m_mockData[2].m_event == NS_DM_Client::e_sessionStart);
        BOOST_CHECK(notify_center->m_mockData[2].m_resultCode == NS_DM_Client::e_Ok);


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

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

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

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

    delete items;
}

BOOST_AUTO_TEST_CASE(MOTreeCopyCommand_CopyWithManyItem_failed)
{
    // first add two leaf nodes for using it when copy

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

    // creation
    Funambol::Add* add_command = new Funambol::Add;
    Funambol::ArrayList* items =  new Funambol::ArrayList;
    // first item
    Funambol::Item* item1 = new Funambol::Item;
    Funambol::Target* target1 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item1");
    item1->setTarget(target1);
    Funambol::ComplexData data1("MOTreeCopyCommand_CopyWithOneItem_success_Item1");
    item1->setData(&data1);
    items->add(*item1);
    // second item
    Funambol::Item* item2 = new Funambol::Item;
    Funambol::Target* target2 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item2");
    item2->setTarget(target2);
    Funambol::ComplexData data2("MOTreeCopyCommand_CopyWithOneItem_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 copy
    Funambol::Item* item3 = new Funambol::Item;
    Funambol::Source* source3 = new Funambol::Source("./MOTreeCopyCommand_CopyWithOneItem_success/Item1");
    item3->setSource(source3);
    Funambol::Target* target3 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item2");
    item3->setTarget(target3);
    Funambol::ComplexData data3("MOTreeCopyCommand_CopyWithOneItem_success_item2");
    item3->setData(&data3);

    // forth item for fail copy
    Funambol::Item* item4 = new Funambol::Item;
    Funambol::Source* source4 = new Funambol::Source("./MOTreeCopyCommand_CopyWithOneItem_success/Item3"); // no existing item
    item4->setSource(source4);
    Funambol::Target* target4 = new Funambol::Target("./MOTreeCopyCommand_CopyWithOneItem_success/Item2");
    item4->setTarget(target4);
    Funambol::ComplexData data4("MOTreeCopyCommand_CopyWithOneItem_success_item2");
    item4->setData(&data4);

    items->add(*item3);
    items->add(*item4); // must fail on this item
    items->add(*item3);

    Funambol::Copy* copy_command = new Funambol::Copy;
    copy_command->setItems(items);
    CopyPtr copy_ptr(copy_command);
    MOTreeCopyCommand tree_copy_command(S_ProfileHolder, copy_ptr, "1", 0);

    BOOST_CHECK(tree_copy_command.Execute() == true);


    // check notifications
    BOOST_CHECK(notify_center->m_mockData.size() == 6); // must be notifications: start and finish
    if (notify_center->m_mockData.size() == 6)
    {
        BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Copy);
        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("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Copy);
        BOOST_CHECK(notify_center->m_mockData[1].m_event == NS_DM_Client::e_sessionStart);
        BOOST_CHECK(notify_center->m_mockData[1].m_resultCode == NS_DM_Client::e_Ok);

        BOOST_CHECK(notify_center->m_mockData[2].m_URI.compare("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[2].m_command == NS_DM_Client::e_Copy);
        BOOST_CHECK(notify_center->m_mockData[2].m_event == NS_DM_Client::e_sessionStart);
        BOOST_CHECK(notify_center->m_mockData[2].m_resultCode == NS_DM_Client::e_Ok);


        BOOST_CHECK(notify_center->m_mockData[3].m_URI.compare("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[3].m_command == NS_DM_Client::e_Copy);
        BOOST_CHECK(notify_center->m_mockData[3].m_event == NS_DM_Client::e_sessionEnd);
        BOOST_CHECK(notify_center->m_mockData[3].m_resultCode != NS_DM_Client::e_Ok);

        BOOST_CHECK(notify_center->m_mockData[4].m_URI.compare("./MOTreeCopyCommand_CopyWithOneItem_success/Item2") == 0); // must be target
        BOOST_CHECK(notify_center->m_mockData[4].m_command == NS_DM_Client::e_Copy);
        BOOST_CHECK(notify_center->m_mockData[4].m_event == NS_DM_Client::e_sessionEnd);
        BOOST_CHECK(notify_center->m_mockData[4].m_resultCode != NS_DM_Client::e_Ok);

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

    delete target4;
    delete source4;
    delete item4;
    delete target3;
    delete source3;
    delete item3;
    delete target2;
    delete item2;
    delete target1;
    delete item1;

    delete items;


}
