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

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

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

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

BOOST_AUTO_TEST_CASE(MOTreeDeleteCommand_DeleteWithOneItem_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;
    Funambol::Item* item = new Funambol::Item;
    Funambol::Target* target = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithOneItem_success/Item");
    item->setTarget(target);
    Funambol::ComplexData data("MOTreeDeleteCommand_DeleteWithOneItem_success_Item");
    item->setData(&data);
    items->add(*item);

    // 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 delete command
    notify_center->clearMockData();

    Funambol::Delete* delete_command = new Funambol::Delete;
    delete_command->setItems(items);
    DeletePtr delete_ptr(delete_command);
    MOTreeDeleteCommand tree_delete_command(S_ProfileHolder, delete_ptr, "1", 0);
    BOOST_CHECK(tree_delete_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("./MOTreeDeleteCommand_DeleteWithOneItem_success/Item") == 0);
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithOneItem_success/Item") == 0);
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Delete);
        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 item;

    delete items;
}

BOOST_AUTO_TEST_CASE(MOTreeDeleteCommand_DeleteWithManyItem_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 nodes first
    // creation
    Funambol::Add* add_command = new Funambol::Add;
    // first
    Funambol::Item* item1 = new Funambol::Item;
    Funambol::Target* target1 = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item1");
    item1->setTarget(target1);
    Funambol::ComplexData data1("MOTreeDeleteCommand_DeleteWithManyItem_success_Item1");
    item1->setData(&data1);
    items->add(*item1);
    // second
    Funambol::Item* item2 = new Funambol::Item;
    Funambol::Target* target2 = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item2");
    item2->setTarget(target2);
    Funambol::ComplexData data2("MOTreeDeleteCommand_DeleteWithManyItem_success_Item2");
    item2->setData(&data2);
    items->add(*item2);
    // third
    Funambol::Item* item3 = new Funambol::Item;
    Funambol::Target* target3 = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item3");
    item3->setTarget(target3);
    Funambol::ComplexData data3("MOTreeDeleteCommand_DeleteWithManyItem_success_Item3");
    item3->setData(&data3);
    items->add(*item3);

    // add 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 delete command
    notify_center->clearMockData();

    Funambol::Delete* delete_command = new Funambol::Delete;
    delete_command->setItems(items);
    DeletePtr delete_ptr(delete_command);
    MOTreeDeleteCommand tree_delete_command(S_ProfileHolder, delete_ptr, "1", 0);
    BOOST_CHECK(tree_delete_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("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[2].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[3].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[4].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_success/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[5].m_command == NS_DM_Client::e_Delete);
        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;
}

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

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

    Funambol::Item* item = new Funambol::Item;
    Funambol::Target* target = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithOneItem_failed/Item"); // item not exist
    item->setTarget(target);
    Funambol::ComplexData data("MOTreeDeleteCommand_DeleteWithOneItem_failed_Item");
    item->setData(&data);
    items->add(*item);

    Funambol::Delete* delete_command = new Funambol::Delete;
    delete_command->setItems(items);
    DeletePtr delete_ptr(delete_command);
    MOTreeDeleteCommand tree_delete_command(S_ProfileHolder, delete_ptr, "1", 0);
    BOOST_CHECK(tree_delete_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("./MOTreeDeleteCommand_DeleteWithOneItem_failed/Item") == 0);
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithOneItem_failed/Item") == 0);
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Delete);
        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 item;

    delete items;
}

BOOST_AUTO_TEST_CASE(MOTreeDeleteCommand_DeleteWithManyItem_failed)
{
    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 nodes first
    // creation
    Funambol::Add* add_command = new Funambol::Add;
    // first
    Funambol::Item* item1 = new Funambol::Item;
    Funambol::Target* target1 = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item1");
    item1->setTarget(target1);
    Funambol::ComplexData data1("MOTreeDeleteCommand_DeleteWithManyItem_failed_Item1");
    item1->setData(&data1);
    items->add(*item1);
    // second
    Funambol::Item* item2 = new Funambol::Item;
    Funambol::Target* target2 = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item2");
    item2->setTarget(target2);
    Funambol::ComplexData data2("MOTreeDeleteCommand_DeleteWithManyItem_failed_Item2");
    item2->setData(&data2);
    items->add(*item2);
    // third
    Funambol::Item* item3 = new Funambol::Item;
    Funambol::Target* target3 = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item3");
    item3->setTarget(target3);
    Funambol::ComplexData data3("MOTreeDeleteCommand_DeleteWithManyItem_failed_Item3");
    item3->setData(&data3);
    items->add(*item3);

    // add 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 delete command
    notify_center->clearMockData();

    // forth
    Funambol::Item* item4 = new Funambol::Item;
    Funambol::Target* target4 = new Funambol::Target("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item4");
    item4->setTarget(target4);
    Funambol::ComplexData data4("MOTreeDeleteCommand_DeleteWithManyItem_failed_Item4");
    item4->setData(&data4);
    items->add(*item4);

    Funambol::Delete* delete_command = new Funambol::Delete;
    delete_command->setItems(items);
    DeletePtr delete_ptr(delete_command);
    MOTreeDeleteCommand tree_delete_command(S_ProfileHolder, delete_ptr, "1", 0);
    BOOST_CHECK(tree_delete_command.Execute() == true);

    // check notifications
    BOOST_CHECK(notify_center->m_mockData.size() == 8); // must be notifications: start and finish
    if (notify_center->m_mockData.size() == 8)
    {
        BOOST_CHECK(notify_center->m_mockData[0].m_URI.compare("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[0].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[1].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[2].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item4") == 0);
        BOOST_CHECK(notify_center->m_mockData[3].m_command == NS_DM_Client::e_Delete);
        BOOST_CHECK(notify_center->m_mockData[3].m_event == NS_DM_Client::e_sessionStart);
        BOOST_CHECK(notify_center->m_mockData[3].m_resultCode == NS_DM_Client::e_Ok);

        BOOST_CHECK(notify_center->m_mockData[4].m_URI.compare("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item1") == 0);
        BOOST_CHECK(notify_center->m_mockData[4].m_command == NS_DM_Client::e_Delete);
        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("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item2") == 0);
        BOOST_CHECK(notify_center->m_mockData[5].m_command == NS_DM_Client::e_Delete);
        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);

        BOOST_CHECK(notify_center->m_mockData[6].m_URI.compare("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item3") == 0);
        BOOST_CHECK(notify_center->m_mockData[6].m_command == NS_DM_Client::e_Delete);
        BOOST_CHECK(notify_center->m_mockData[6].m_event == NS_DM_Client::e_sessionEnd);
        BOOST_CHECK(notify_center->m_mockData[6].m_resultCode != NS_DM_Client::e_Ok);

        BOOST_CHECK(notify_center->m_mockData[7].m_URI.compare("./MOTreeDeleteCommand_DeleteWithManyItem_failed/Item4") == 0);
        BOOST_CHECK(notify_center->m_mockData[7].m_command == NS_DM_Client::e_Delete);
        BOOST_CHECK(notify_center->m_mockData[7].m_event == NS_DM_Client::e_sessionEnd);
        BOOST_CHECK(notify_center->m_mockData[7].m_resultCode != NS_DM_Client::e_Ok);
    }

    delete target4;
    delete item4;

    delete target3;
    delete item3;

    delete target2;
    delete item2;

    delete target1;
    delete item1;

    delete items;


}
