#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 <syncml/core/Item.h>
#include <syncml/core/Add.h>

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

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

BOOST_AUTO_TEST_CASE(MOTreeAddCommand_AddWithOneItem_success)
{
    // creation
    Funambol::Add* add_command = new Funambol::Add;
    // initialization with URI
    Funambol::Item* item = new Funambol::Item;
    Funambol::ArrayList* items =  new Funambol::ArrayList;
    Funambol::Target* target = new Funambol::Target("./MOTreeAddCommand_AddWithOneItem_success/Item");

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

    if (add_command && item && items && target && S_ProfileHolder)
    {
        item->setTarget(target);

        Funambol::ComplexData data("MOTreeAddCommand_AddWithOneItem_success");
        item->setData(&data);
        items->add(*item);
        add_command->setItems(items);

        AddPtr ptr(add_command);

        MOTreeAddCommand command(S_ProfileHolder, ptr, "1", 0);

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

        delete target;
        delete items;
        delete item;
    }

    // check notifications
    BOOST_CHECK(notify_center->m_mockData.size() == 2); // must be 2 notifications: start and finish
    if (notify_center->m_mockData.size() == 2)
    {
        BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeAddCommand_AddWithOneItem_success/Item") == 0);
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithOneItem_success/Item") == 0);
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Add);
        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);
    }

    fs::remove_all(NS_DM_Client::NS_DataStorage::GetBasePath());
}

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

BOOST_AUTO_TEST_CASE(MOTreeAddCommand_AddWithOneItem_failed)
{
    // creation
    Funambol::Add* add_command = new Funambol::Add;
    // initialization with URI
    Funambol::Item* item = new Funambol::Item;
    Funambol::ArrayList* items =  new Funambol::ArrayList;
    Funambol::Target* target = new Funambol::Target("./MOTreeAddCommand_AddWithOneItem_failed/Item");

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

    if (add_command && item && items && target && S_ProfileHolder)
    {
        item->setTarget(target);

        Funambol::ComplexData data("MOTreeAddCommand_AddWithOneItem_failed");
        item->setData(&data);
        items->add(*item);
        add_command->setItems(items);

        AddPtr ptr(add_command);

        MOTreeAddCommand command(S_ProfileHolder, ptr, "1", 0);

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

        // check notifications
        BOOST_CHECK(notify_center->m_mockData.size() == 2); // must be 2 notifications: start and finish
        if (notify_center->m_mockData.size() == 2)
        {
            BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeAddCommand_AddWithOneItem_failed/Item") == 0);
            BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Add);
            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("./MOTreeAddCommand_AddWithOneItem_failed/Item") == 0);
            BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Add);
            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);
        }

        // simulate fail by try Add existing leaf
        notify_center->clearMockData();

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

        // check notifications
        BOOST_CHECK(notify_center->m_mockData.size() == 2); // must be 2 notifications: start and finish
        if (notify_center->m_mockData.size() == 2)
        {
            BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeAddCommand_AddWithOneItem_failed/Item") == 0);
            BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Add);
            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("./MOTreeAddCommand_AddWithOneItem_failed/Item") == 0);
            BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Add);
            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 items;
        delete item;
    }

    fs::remove_all(NS_DM_Client::NS_DataStorage::GetBasePath());
}

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

BOOST_AUTO_TEST_CASE(MOTreeAddCommand_AddWithManyItem_success)
{

    // check notifications
    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("./MOTreeAddCommand_AddWithManyItem_success/Item1");
    item1->setTarget(target1);
    Funambol::ComplexData data1("MOTreeAddCommand_AddWithOneItem_success_Item1");
    item1->setData(&data1);
    items->add(*item1);
    // second item
    Funambol::Item* item2 = new Funambol::Item;
    Funambol::Target* target2 = new Funambol::Target("./MOTreeAddCommand_AddWithManyItem_success/Item2");
    item2->setTarget(target2);
    Funambol::ComplexData data2("MOTreeAddCommand_AddWithOneItem_success_item2");
    item2->setData(&data2);
    items->add(*item2);
    // third item
    Funambol::Item* item3 = new Funambol::Item;
    Funambol::Target* target3 = new Funambol::Target("./MOTreeAddCommand_AddWithManyItem_success/Item3");
    item3->setTarget(target3);
    Funambol::ComplexData data3("MOTreeAddCommand_AddWithOneItem_success_item3");
    item3->setData(&data3);
    items->add(*item3);

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

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

    delete items;

    // check notifications
    BOOST_CHECK(notify_center->m_mockData.size() == 6); // must be 6 notifications: 3 start and 3 finish
    if (notify_center->m_mockData.size() == 6)
    {
        BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeAddCommand_AddWithManyItem_success/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_success/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_success/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[2].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_success/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[3].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_success/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[4].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_success/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[5].m_command == NS_DM_Client::e_Add);
        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);
    }

    fs::remove_all(NS_DM_Client::NS_DataStorage::GetBasePath());
}

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

BOOST_AUTO_TEST_CASE(MOTreeAddCommand_AddWithManyItem_failed)
{
    // check notifications
    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("./MOTreeAddCommand_AddWithManyItem_failed/Item1");
    item1->setTarget(target1);
    Funambol::ComplexData data1("MOTreeAddCommand_AddWithManyItem_failed");
    item1->setData(&data1);
    items->add(*item1);
    // second item
    Funambol::Item* item2 = new Funambol::Item;
    Funambol::Target* target2 = new Funambol::Target("./MOTreeAddCommand_AddWithManyItem_failed/Item2");
    item2->setTarget(target2);
    Funambol::ComplexData data2("MOTreeAddCommand_AddWithManyItem_failed");
    item2->setData(&data2);
    items->add(*item2);
    // third item
    Funambol::Item* item3 = new Funambol::Item;
    Funambol::Target* target3 = new Funambol::Target("./MOTreeAddCommand_AddWithManyItem_failed/Item3");
    item3->setTarget(target3);
    Funambol::ComplexData data3("MOTreeAddCommand_AddWithManyItem_failed");
    item3->setData(&data3);
    items->add(*item3);

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

    // check notifications
    BOOST_CHECK(notify_center->m_mockData.size() == 6); // must be 6 notifications: 3 start and 3 finish
    if (notify_center->m_mockData.size() == 6)
    {
        BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeAddCommand_AddWithManyItem_failed/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[2].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[3].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[4].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[5].m_command == NS_DM_Client::e_Add);
        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);
    }


    // simulate fail by try Add existing leaf
    notify_center->clearMockData();

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

     // check notifications
    BOOST_CHECK(notify_center->m_mockData.size() == 6); // must be 6 notifications: 3 start and 3 finish
    if (notify_center->m_mockData.size() == 6)
    {
        BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeAddCommand_AddWithManyItem_failed/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[2].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[3].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[4].m_command == NS_DM_Client::e_Add);
        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("./MOTreeAddCommand_AddWithManyItem_failed/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[5].m_command == NS_DM_Client::e_Add);
        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 item3;
    delete target2;
    delete item2;
    delete target1;
    delete item1;

    delete items;





}
