//#define BOOST_TEST_MAIN

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

#include "../Node.h"
#include <iostream>
#include "treemanager/MOTreeManager.h"
#include "MockDataStorage.h"
#include <syncml/core/Item.h>
#include "Common.h"
#include "commontypes.h"

const std::string S_root;
//const std::string S_workingDirectory("MockMOTree");

using namespace NS_DM_Client;
namespace fs = boost::filesystem;

BOOST_AUTO_TEST_CASE(GetValueForLeaf)
{
	URI uri = "GetValueForLeaf/Node1/Node2";
	NS_DM_Client::Node leaf(uri, S_dataStorage);
	String content("some content");
	leaf.SetContent(content.c_str());
	leaf.SetProperty(NS_DM_Client::e_format, "chr");
	leaf.SetProperty(NS_DM_Client::e_type, "text/plain");
	leaf.SetProperty(NS_DM_Client::e_ACL, "");

	URI realContent;
	BOOST_CHECK(S_treeManager->GetValue(uri, realContent));
	//std::cout << "realContent = " << realContent << std::endl;
	BOOST_CHECK(content == realContent);

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

// TODO: add test GetUnexistingProperty

BOOST_AUTO_TEST_CASE(GetItemForLeaf)
{
	// set node before retriving
	URI uri = "GetItemForLeaf/Node1/Node2";
	NS_DM_Client::Node leaf(uri, S_dataStorage);
	leaf.SetProperty(NS_DM_Client::e_format, "chr");
	leaf.SetProperty(NS_DM_Client::e_type, "text/plain");
	leaf.SetProperty(NS_DM_Client::e_ACL, "");

	String content("Some data");
	leaf.SetContent(content);

	// retrieve data from storage
	Funambol::Item item;
	NS_DM_Client::StatusCode code = S_treeManager->Get(uri, item);
	BOOST_CHECK(NS_DM_Client::e_Ok == code);
	std::string realData = item.getData()->getData();
	BOOST_CHECK(realData == "Some data");

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

// this test is commented because of MockDataStorage should create intermidiate folders
BOOST_AUTO_TEST_CASE(AddNodeWithUnexistingUri)
{
	// add node
 	URI uri = "AddNodeWithUnexistingUri/Node1/Node2/NodeUnexisted";
 	NS_DM_Client::Node node(uri, S_dataStorage);
 	std::string content("Some data");

 	Funambol::Item newItem;
	Funambol::Meta meta;
	meta.setFormat("chr");
	meta.setType("text/plain");
	newItem.setMeta(&meta);
	Funambol::ComplexData complexData(content.c_str());
 	newItem.setData(&complexData);

 	BOOST_CHECK(S_treeManager->Add(uri, newItem) == NS_DM_Client::e_Ok);

 	// get added node
 	Funambol::Item realItem;
	S_treeManager->Get(uri, realItem);
 	std::string realData = realItem.getData()->getData();
 	BOOST_CHECK(realData == content);

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

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

BOOST_AUTO_TEST_CASE(DeleteExistingNode)
{
	// add node
	URI uri = "DeleteExistingNode/Node1/Node2";
	NS_DM_Client::Node node(uri, S_dataStorage);
	std::string content("Some data");

	Funambol::Item newItem;
	Funambol::Meta meta;
	meta.setFormat("chr");
	meta.setType("text/plain");
	newItem.setMeta(&meta);
	Funambol::ComplexData complexData(content.c_str());
	newItem.setData(&complexData);
	Funambol::Target target(uri.c_str());
	newItem.setTarget(&target);

	S_treeManager->Add(uri, newItem);

	// remove added node
	BOOST_CHECK( NS_DM_Client::e_Ok == S_treeManager->Delete(uri));
	BOOST_CHECK(S_treeManager->Get(uri, newItem) == NS_DM_Client::e_NotFound);

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

BOOST_AUTO_TEST_CASE(DeleteUnexistingNode)
{
	// add node
	URI uri = "DeleteUnexistingNode/Node1/Node2";

	Funambol::Item item;
	BOOST_CHECK(S_treeManager->Get(uri, item) == NS_DM_Client::e_NotFound);
	BOOST_CHECK(NS_DM_Client::e_NotFound == S_treeManager->Delete(uri));

	String path = NS_DM_Client::NS_DataStorage::GetBasePath() + (String)"/" + c_testProfile;
    fs::remove_all(path.c_str());
}
//-------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(ReplaceUnexistingNode)
{
	URI uri = "ReplaceUnexistingNode/Node1/Node2";
	Funambol::Item item;
	BOOST_CHECK(S_treeManager->Get(uri, item) == NS_DM_Client::e_NotFound);
	BOOST_CHECK(NS_DM_Client::e_NotFound == S_treeManager->Replace(uri, item));

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

BOOST_AUTO_TEST_CASE(ReplaceNode)
{
	// add node
	URI uri = "ReplaceNode/Node1/Node2";
	Funambol::Item item;
	Funambol::Meta meta;
	meta.setFormat("chr");
	meta.setType("text/plain");
	meta.setSize(9);
	item.setMeta(&meta);
	std::string content("Some data");
	Funambol::ComplexData complexData(content.c_str());
	item.setData(&complexData);

	S_treeManager->Add(uri, item);

	Funambol::Item newItem;
	newItem.setMeta(&meta);
	std::string newContent("Some another data");
	complexData.setData(newContent.c_str());
	newItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Replace(uri, newItem));

	Funambol::Item realItem;
	S_treeManager->Get(uri, realItem);
	std::string realData = realItem.getData()->getData();
	BOOST_CHECK(realData == newContent);

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

BOOST_AUTO_TEST_CASE(CopyLeafNodeToExistingDestinationNode)
{
	// add root with ACL = Get=*&Add=*
	NS_DM_Client::Node root("CopyLeafNodeToExistingDestinationNode/RootNode", S_dataStorage);
	root.SetProperty(NS_DM_Client::e_format, "node");
	root.SetProperty(NS_DM_Client::e_type, "node");
	root.SetProperty(NS_DM_Client::e_ACL, "Get=*&Add=*");

	// add source node
	URI uri1 = "CopyLeafNodeToExistingDestinationNode/RootNode/Node1/Node2/SourceNode";
	Funambol::Item sourceItem;
	Funambol::Meta meta;
	meta.setFormat("chr");
	meta.setType("text/plain");
	sourceItem.setMeta(&meta);
	std::string oldContent("Some data");
	Funambol::ComplexData complexData(oldContent.c_str());
	sourceItem.setData(&complexData);

	// add destination node
	URI uri2 = "CopyLeafNodeToExistingDestinationNode/RootNode/Node1/Node2/DestNode";
	Funambol::Item destItem;
	meta.setFormat("chr");
	meta.setType("text/plain");
	destItem.setMeta(&meta);
	std::string newContent("Some another data");
	complexData.setData(newContent.c_str());
	destItem.setData(&complexData);

	S_treeManager->Add(uri1, sourceItem);
	S_treeManager->Add(uri2, destItem);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Copy(uri1, uri2));

	Funambol::Item realItem;
	S_treeManager->Get(uri2, realItem);
	std::string realData = realItem.getData()->getData();
	BOOST_CHECK(realData == oldContent);

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


BOOST_AUTO_TEST_CASE(CopyLeafNodeToNotExistingDestinationNode)
{
	// add root with ACL = Get=*&Add=*
	NS_DM_Client::Node root("CopyLeafNodeToNotExistingDestinationNode/RootNode", S_dataStorage);
	root.SetProperty(NS_DM_Client::e_format, "node");
	root.SetProperty(NS_DM_Client::e_type, "node");
	root.SetProperty(NS_DM_Client::e_ACL, "Get=*&Add=*");

	// add source node
	URI uri1 = "CopyLeafNodeToNotExistingDestinationNode/RootNode/Node1/Node2/SourceNode";
	Funambol::Item sourceItem;
	Funambol::Meta meta;
	meta.setFormat("chr");
	meta.setType("text/plain");
	sourceItem.setMeta(&meta);
	std::string oldContent("source node content");
	Funambol::ComplexData complexData(oldContent.c_str());
	sourceItem.setData(&complexData);

	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri1, sourceItem));

	URI uri2 = "CopyLeafNodeToNotExistingDestinationNode/RootNode/SomeInteriorNode1/Node2/DestNode";
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Copy(uri1, uri2));

	Funambol::Item realItem;
	S_treeManager->Get(uri2, realItem);
	std::string realData = realItem.getData()->getData();
	BOOST_CHECK(realData == oldContent);

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


BOOST_AUTO_TEST_CASE(CopyInteriorNode)
{
	// add root with ACL = Get=*&Add=*
	NS_DM_Client::Node root("CopyInteriorNode/RootNode", S_dataStorage);
	root.SetProperty(NS_DM_Client::e_format, "node");
	root.SetProperty(NS_DM_Client::e_type, "node");
	root.SetProperty(NS_DM_Client::e_ACL, "Get=*&Add=*");

	// add childs
	URI uri = "CopyInteriorNode/RootNode/Node1/Node2/SourceNode";
	Funambol::Item sourceItem;
	Funambol::Meta meta;
	meta.setFormat("chr");
	meta.setType("text/plain");
	sourceItem.setMeta(&meta);
	std::string oldContent("Some data");
	Funambol::ComplexData complexData(oldContent.c_str());
	sourceItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri, sourceItem));

	uri = "CopyInteriorNode/RootNode/Subnode/Node1/SourceNode";
	sourceItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri, sourceItem));

	uri = "CopyInteriorNode/RootNode/Subnode/Node2/SourceNode2";
	sourceItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri, sourceItem));

	uri = "CopyInteriorNode/RootNode/Subnode/LeafNode";
	sourceItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri, sourceItem));

	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Copy("CopyInteriorNode/RootNode", "CopyInteriorNode/copy_dest"));

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


BOOST_AUTO_TEST_CASE(CheckPermanentStatus)
{
	// add node
	URI uri = "CheckPermanentStatus/PermanentNode";
	fs::path path(uri, fs::native);

	NS_DM_Client::Node root("CopyInteriorNode/RootNode", S_dataStorage);
	root.SetProperty(NS_DM_Client::e_format, "chr");
	root.SetProperty(NS_DM_Client::e_type, "text/plain");
	root.SetProperty(NS_DM_Client::e_ACL, "Get=*&Delete=*");
    root.SetContent("permanent leaf node");
    root.SetPermanent();

    BOOST_CHECK(true == root.IsPermanent());

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

BOOST_AUTO_TEST_CASE(ReplaceNamePropertyOfNode)
{
	NS_DM_Client::Node root("ReplaceNamePropertyOfNode/RootNode", S_dataStorage);

	root.SetProperty(NS_DM_Client::e_format, "node");
	root.SetProperty(NS_DM_Client::e_type, "node");
	root.SetProperty(NS_DM_Client::e_ACL, "Get=*&Add=*");

	// add childs
	URI uri = "ReplaceNamePropertyOfNode/RootNode/Node1/Node2/SourceNode";
	Funambol::Item sourceItem;
	Funambol::Meta meta;
	meta.setFormat("chr");
	meta.setType("text/plain");
	sourceItem.setMeta(&meta);
	std::string oldContent("Some data");
	Funambol::ComplexData complexData(oldContent.c_str());
	sourceItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri, sourceItem));

	uri = "ReplaceNamePropertyOfNode/RootNode/Subnode/Node1/SourceNode";
	sourceItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri, sourceItem));

	uri = "ReplaceNamePropertyOfNode/RootNode/Subnode/Node2/SourceNode2";
	sourceItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri, sourceItem));

	uri = "ReplaceNamePropertyOfNode/RootNode/Subnode/LeafNode";
	sourceItem.setData(&complexData);
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Add(uri, sourceItem));

	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->ReplacePropertyValue("ReplaceNamePropertyOfNode/RootNode", "Name", "ReplacedNode"));

	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->Get("ReplaceNamePropertyOfNode/ReplacedNode/Subnode/Node2/SourceNode2", sourceItem));

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

