#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 <syncml/core/ObjectDel.h>

#include "Common.h"
#include "commontypes.h"

using namespace NS_DM_Client;

const std::string S_root;

namespace fs = boost::filesystem;

void AddNode(const URI& name)
{
	NS_DM_Client::Node node(name, S_dataStorage);
	node.SetProperty(NS_DM_Client::e_format, "node");
	node.SetProperty(NS_DM_Client::e_type, "text/plain");
	node.SetProperty(NS_DM_Client::e_ACL, "");
}
//-------------------------------------------------------------------------------------------

void AddLeaf(const URI& name, String& value)
{
	NS_DM_Client::Node leaf(name, S_dataStorage);
	leaf.SetContent(value.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, "");
}
//-------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(GetAttributeTNDSOneProperty)
{
	// add leaf node
	URI uri = "Leaf";
	NS_DM_Client::Node node(uri, S_dataStorage);
	node.SetContent("some content");
	node.SetProperty(NS_DM_Client::e_format, "chr");
	node.SetProperty(NS_DM_Client::e_type, "text/plain");
	node.SetProperty(NS_DM_Client::e_ACL, "");

	NS_DM_Client::IMOTreeManager::RequiredProperties requiredProp;
	requiredProp.push_back(NS_DM_Client::e_TNDS_name);
	Funambol::StringBuffer* buffer = 0;
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->GetAttributeTNDS(uri, requiredProp, buffer));

	std::string expectedBuffer(
		"<MgmtTree xmlns='syncml:dmddf1.2'>"
		"<VerDTD>1.2</VerDTD>\n"
		"<Node>"
		"<NodeName>Leaf</NodeName>\n"
		"<RTProperties>"
		"</RTProperties>"
		"</Node>"
		"</MgmtTree>"
		);
	std::string realBuffer = buffer->c_str();
	BOOST_CHECK(expectedBuffer == realBuffer);
	Funambol::deleteStringBuffer(&buffer);

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

BOOST_AUTO_TEST_CASE(GetAttributeTNDSUnexistingNode)
{
	URI uri = "Node1";
	NS_DM_Client::IMOTreeManager::RequiredProperties requiredProp;
	Funambol::StringBuffer* buffer = 0;
	BOOST_CHECK(NS_DM_Client::e_CommandFailed == S_treeManager->GetAttributeTNDS(uri, requiredProp, buffer));
	Funambol::deleteStringBuffer(&buffer);
}
//-------------------------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(GetAttributeTNDSLeaf)
{
	// add Node1
	URI uriNode1 = "Node1";
	NS_DM_Client::Node node1(uriNode1, S_dataStorage);
	node1.SetProperty(NS_DM_Client::e_format, "node");
	node1.SetProperty(NS_DM_Client::e_type, "text/plain");
	node1.SetProperty(NS_DM_Client::e_ACL, "");

	// add subnode of Node1
	URI uriNode1_1 = uriNode1 + "/Node1_1";
	NS_DM_Client::Node node1_1(uriNode1_1, S_dataStorage);
	node1_1.SetProperty(NS_DM_Client::e_format, "node");
	node1_1.SetProperty(NS_DM_Client::e_type, "text/plain");
	node1_1.SetProperty(NS_DM_Client::e_ACL, "");

	// add leaf
	URI uriLeaf = uriNode1_1 + "/Leaf";
	NS_DM_Client::Node leaf(uriLeaf, S_dataStorage);
	std::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, "");

	// this node should be skipped in result
	URI uriNode1_2 = "Node1/Node1_2";
	NS_DM_Client::Node node1_2(uriNode1_2, S_dataStorage);
	node1_2.SetContent("some content");
	node1_2.SetProperty(NS_DM_Client::e_format, "node");
	node1_2.SetProperty(NS_DM_Client::e_type, "text/plain");
	node1_2.SetProperty(NS_DM_Client::e_ACL, "");

	NS_DM_Client::IMOTreeManager::RequiredProperties requiredProp;
	requiredProp.push_back(NS_DM_Client::e_TNDS_ACL);
	requiredProp.push_back(NS_DM_Client::e_TNDS_name);
	requiredProp.push_back(NS_DM_Client::e_TNDS_format);
	requiredProp.push_back(NS_DM_Client::e_TNDS_type);
	requiredProp.push_back(NS_DM_Client::e_TNDS_size);
	requiredProp.push_back(NS_DM_Client::e_TNDS_title);
	requiredProp.push_back(NS_DM_Client::e_TNDS_tstamp);
	requiredProp.push_back(NS_DM_Client::e_TNDS_verNo);
	requiredProp.push_back(NS_DM_Client::e_TNDS_value);

	Funambol::StringBuffer* buffer = 0;
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->GetAttributeTNDS(uriLeaf, requiredProp, buffer));

	std::string expectedBuffer(
		"<MgmtTree xmlns='syncml:dmddf1.2'>"
		"<VerDTD>1.2</VerDTD>\n"
// 		"<Node>"
// 		"<NodeName>Node1</NodeName>\n"
// 		"<RTProperties>"
// 		"<Format>node</Format>\n"
// 		"<Type>text/plain</Type>\n"
// 		"</RTProperties>"
//		"</Node>"
// 		"<Node>"
// 		"<Path>Node1</Path>\n"
// 		"<NodeName>Node1_1</NodeName>\n"
// 		"<RTProperties>"
// 		"<Format>node</Format>\n"
// 		"<Type>text/plain</Type>\n"
// 		"</RTProperties>"
//		"</Node>"
		"<Node>"
		"<Path>Node1/Node1_1</Path>\n"
		"<NodeName>Leaf</NodeName>\n"
		"<Value><![CDATA[some content]]></Value>\n"
		"<RTProperties>"
			"<ACL></ACL>\n"
			"<Format>chr</Format>\n"
			"<Type>text/plain</Type>\n"
			"<Size>0</Size>\n"
		"</RTProperties>"
		"</Node>"

		"</MgmtTree>"
		);
	std::string realBuffer = buffer->c_str();
	BOOST_CHECK(expectedBuffer == realBuffer);
	if (expectedBuffer != realBuffer)
    {
		std::cout << "realBuffer: \n" << realBuffer << std::endl;
		std::cout << std::endl;
		std::cout << "expectedBuffer: \n" << expectedBuffer << std::endl;
    }

	Funambol::deleteStringBuffer(&buffer);

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

BOOST_AUTO_TEST_CASE(GetAttributeTNDSInteriorNode)
{
	// add Node1
	URI uriNode1 = "Node1";
	AddNode(uriNode1);
	// add subnode of Node1 - Node1_1
	URI uriNode1_1 = uriNode1 + "/Node1_1";
	AddNode(uriNode1_1);
// 	// add leaf for Node1_1
//  	URI uriLeaf1_1 = uriNode1_1 + "/Leaf1_1";
// 	String content1_1("some content 1_1");
// 	AddLeaf(uriLeaf1_1, content1_1);

	// add subnode of Node1_1 - Node1_1_1
	URI uriNode1_1_1 = uriNode1_1 + "/Node1_1_1";
	AddNode(uriNode1_1_1);

	// add leaf for Node1_1_1
	URI uriLeaf1_1_1 = uriNode1_1_1 + "/Leaf1_1_1";
	String content1_1_1("some content 1_1_1");
	AddLeaf(uriLeaf1_1_1, content1_1_1);

	// this node should be skipped in result
	URI uriNode1_2 = uriNode1 + "/Node1_2";
	AddNode(uriNode1_2);

	NS_DM_Client::IMOTreeManager::RequiredProperties requiredProp;
	requiredProp.push_back(NS_DM_Client::e_TNDS_ACL);
	requiredProp.push_back(NS_DM_Client::e_TNDS_name);
	requiredProp.push_back(NS_DM_Client::e_TNDS_format);
	requiredProp.push_back(NS_DM_Client::e_TNDS_type);
	requiredProp.push_back(NS_DM_Client::e_TNDS_size);
	requiredProp.push_back(NS_DM_Client::e_TNDS_title);
	requiredProp.push_back(NS_DM_Client::e_TNDS_tstamp);
	requiredProp.push_back(NS_DM_Client::e_TNDS_verNo);
	requiredProp.push_back(NS_DM_Client::e_TNDS_value);

	Funambol::StringBuffer* buffer = 0;
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->GetAttributeTNDS(uriNode1_1, requiredProp, buffer));

	std::string expectedBuffer(
		"<MgmtTree xmlns='syncml:dmddf1.2'>"
		"<VerDTD>1.2</VerDTD>\n"
// 		"<Node>"
// 			"<NodeName>Node1</NodeName>\n"
// 			"<RTProperties>"
// 				"<Format>node</Format>\n"
// 				"<Type>text/plain</Type>\n"
// 			"</RTProperties>"
//		"</Node>"
//
 		"<Node>"
			"<Path>Node1</Path>\n"
			"<NodeName>Node1_1</NodeName>\n"
			"<RTProperties>"
				"<ACL></ACL>\n"
				"<Format>node</Format>\n"
				"<Type>text/plain</Type>\n"
			"</RTProperties>"
		"</Node>"

// 		"<Node>"
// 			"<Path>Node1/Node1_1</Path>\n"
// 			"<NodeName>Leaf1_1</NodeName>\n"
// 			"<Value><![CDATA[some content 1_1]]></Value>\n"
// 			"<RTProperties>"
// 				"<ACL></ACL>\n"
// 				"<Format>chr</Format>\n"
// 				"<Type>text/plain</Type>\n"
// 				"<Size>0</Size>\n"
// 			"</RTProperties>"
// 		"</Node>"

		"<Node>"
			"<Path>Node1/Node1_1</Path>\n"
			"<NodeName>Node1_1_1</NodeName>\n"
			"<RTProperties>"
				"<ACL></ACL>\n"
				"<Format>node</Format>\n"
				"<Type>text/plain</Type>\n"
			"</RTProperties>"
		"</Node>"

		"<Node>"
			"<Path>Node1/Node1_1/Node1_1_1</Path>\n"
			"<NodeName>Leaf1_1_1</NodeName>\n"
			"<Value><![CDATA[some content 1_1_1]]></Value>\n"
			"<RTProperties>"
				"<ACL></ACL>\n"
				"<Format>chr</Format>\n"
				"<Type>text/plain</Type>\n"
				"<Size>0</Size>\n"
			"</RTProperties>"
		"</Node>"

		"</MgmtTree>"
		);
	std::string realBuffer = buffer->c_str();
	BOOST_CHECK(expectedBuffer == realBuffer);
	if (!(expectedBuffer == realBuffer))
	{
		std::cout << "realBuffer = " << realBuffer << std::endl;
		std::cout << "realBuffer size = " << realBuffer.size() << std::endl;

		std::cout << std::endl;
		std::cout << "expectedBuffer = " << expectedBuffer << std::endl;
		std::cout << "expectedBuffer size = " << expectedBuffer.size() << std::endl;
	}

	Funambol::deleteStringBuffer(&buffer);

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

BOOST_AUTO_TEST_CASE(GetAttributeStructData)
{
	// add Node1
	URI uriNode1 = "GetAttributeStructData/Node1";
	NS_DM_Client::Node node1(uriNode1, S_dataStorage);
	node1.SetProperty(NS_DM_Client::e_format, "node");
	node1.SetProperty(NS_DM_Client::e_type, "text/plain");
	node1.SetProperty(NS_DM_Client::e_ACL, "");

	// add subnode of Node1
	URI uriNode1_1 = uriNode1 + "/Node1_1";
	NS_DM_Client::Node node1_1(uriNode1_1, S_dataStorage);
	node1_1.SetProperty(NS_DM_Client::e_format, "node");
	node1_1.SetProperty(NS_DM_Client::e_type, "text/plain");
	node1_1.SetProperty(NS_DM_Client::e_ACL, "");

	URI uriLeaf = uriNode1 + "/Leaf";
	NS_DM_Client::Node leaf(uriLeaf, S_dataStorage);
	std::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, "");

	Funambol::ArrayList items;
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->GetAttributeStructData(uriNode1, items));
	BOOST_CHECK(items.size() == 3);

	Funambol::Item* item1 = (Funambol::Item*)items.get(0);
	BOOST_CHECK(uriLeaf == item1->getTarget()->getLocURI()
		|| uriNode1 == item1->getTarget()->getLocURI() || uriNode1_1 == item1->getTarget()->getLocURI());

	Funambol::Item* item2 = (Funambol::Item*)items.get(1);
	BOOST_CHECK(uriLeaf == item2->getTarget()->getLocURI()
		|| uriNode1 == item2->getTarget()->getLocURI() || uriNode1_1 == item2->getTarget()->getLocURI());


	Funambol::Item* item3 = (Funambol::Item*)items.get(2);
	BOOST_CHECK(uriLeaf == item3->getTarget()->getLocURI()
		|| uriNode1 == item3->getTarget()->getLocURI() || uriNode1_1 == item3->getTarget()->getLocURI());

	BOOST_CHECK(std::string(item1->getTarget()->getLocURI()) != item2->getTarget()->getLocURI());
	BOOST_CHECK(std::string(item2->getTarget()->getLocURI()) != item3->getTarget()->getLocURI());

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

BOOST_AUTO_TEST_CASE(GetAttributeTNDSOneNode)
{
	// add leaf node
	URI uri = "Leaf";
	NS_DM_Client::Node node(uri, S_dataStorage);
	node.SetContent("some content");
	node.SetProperty(NS_DM_Client::e_format, "chr");
	node.SetProperty(NS_DM_Client::e_type, "text/plain");
	node.SetProperty(NS_DM_Client::e_ACL, "");

	NS_DM_Client::IMOTreeManager::RequiredProperties requiredProp;
	requiredProp.push_back(NS_DM_Client::e_TNDS_ACL);
	requiredProp.push_back(NS_DM_Client::e_TNDS_name);
	requiredProp.push_back(NS_DM_Client::e_TNDS_format);
	requiredProp.push_back(NS_DM_Client::e_TNDS_type);
	requiredProp.push_back(NS_DM_Client::e_TNDS_size);
	requiredProp.push_back(NS_DM_Client::e_TNDS_title);
	requiredProp.push_back(NS_DM_Client::e_TNDS_tstamp);
	requiredProp.push_back(NS_DM_Client::e_TNDS_verNo);
	requiredProp.push_back(NS_DM_Client::e_TNDS_value);

	Funambol::StringBuffer* buffer = 0;
	BOOST_CHECK(NS_DM_Client::e_Ok == S_treeManager->GetAttributeTNDS(uri, requiredProp, buffer));

	std::string expectedBuffer(
		"<MgmtTree xmlns='syncml:dmddf1.2'>"
			"<VerDTD>1.2</VerDTD>\n"
			"<Node>"
			"<NodeName>Leaf</NodeName>\n"
			"<Value><![CDATA[some content]]></Value>\n"
			"<RTProperties>"
				"<ACL></ACL>\n"
				"<Format>chr</Format>\n"
				"<Type>text/plain</Type>\n"
				"<Size>0</Size>\n" // size is 0 because of MockDataStorage
			"</RTProperties>"
			"</Node>"
			"</MgmtTree>"
	);
	std::string realBuffer = buffer->c_str();
	//std::cout << "realBuffer = " << realBuffer << std::endl;
	BOOST_CHECK(expectedBuffer == realBuffer);
	Funambol::deleteStringBuffer(&buffer);

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