/*
 * Copyright (C) 2009 - 2010 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

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

#include "../Node.h"
#include <iostream>
#include "Common.h"
#include "MockDataStorage.h"

//const std::string S_root;

namespace fs = boost::filesystem;

//-------------------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(CreateLeaf)
{
	std::string uri = "CreateLeaf/Node1/Node2";
	NS_DM_Client::Node leaf(uri, S_dataStorage);
	fs::path path(
	    NS_DM_Client::NS_DataStorage::GetBasePath() + (NS_DM_Client::String)"/"
	    + c_testProfile + (NS_DM_Client::String)"/" + uri, fs::native);

	BOOST_CHECK(!fs::exists(path));

	leaf.SetContent("some content");
	BOOST_CHECK(fs::exists(path));

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

BOOST_AUTO_TEST_CASE(CreateProperties)
{
	std::string uri = "CreateProperties/Node1/Node2";
	NS_DM_Client::Node leaf(uri, S_dataStorage);
	fs::path path(NS_DM_Client::NS_DataStorage::GetBasePath() + (NS_DM_Client::String)"/"
	    + c_testProfile + (NS_DM_Client::String)"/" + uri, fs::native);

	leaf.SetProperty(NS_DM_Client::e_verNo, "version1");
	BOOST_CHECK(fs::exists(path));

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

BOOST_AUTO_TEST_CASE(GetContentForInteriorNode)
{
	std::string uri = "GetContentForInteriorNode/Node1/Node2";
	fs::path path(NS_DM_Client::NS_DataStorage::GetBasePath() + (NS_DM_Client::String)"/"
	    + c_testProfile + (NS_DM_Client::String)"/" + uri, fs::native);
	NS_DM_Client::Node node(uri, S_dataStorage);
	node.SetProperty(NS_DM_Client::e_format, "node");

	std::string realContent;
	//std::cout << "Before GetContent: node = " << &node << std::endl;
	BOOST_CHECK(!node.GetContent(realContent));

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

BOOST_AUTO_TEST_CASE(GetContent)
{
	std::string uri = "GetContent/Node1/Node2";
	NS_DM_Client::Node leaf(uri, S_dataStorage);
	fs::path path(NS_DM_Client::NS_DataStorage::GetBasePath() + (NS_DM_Client::String)"/"
	    + c_testProfile + (NS_DM_Client::String)"/" + uri, fs::native);

	std::string content("some content");
	leaf.SetContent(content.c_str());
	leaf.SetProperty(NS_DM_Client::e_format, "chr");
	BOOST_CHECK(fs::exists(path));

	std::string realContent;
	BOOST_CHECK(leaf.GetContent(realContent));
	//std::cout << "realContent = " << realContent << std::endl;
	BOOST_CHECK(content == realContent);

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

//-------------------------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(GetProperty)
{
	std::string uri = "GetProperty/Node1/Node2";
	NS_DM_Client::Node leaf(uri, S_dataStorage);
	fs::path path(NS_DM_Client::NS_DataStorage::GetBasePath() + (NS_DM_Client::String)"/"
	    + c_testProfile + (NS_DM_Client::String)"/" + uri, fs::native);

	std::string property("version1");
	leaf.SetProperty(NS_DM_Client::e_verNo, property.c_str());
	BOOST_CHECK(fs::exists(path));

	std::string realProperty;
	leaf.GetProperty(NS_DM_Client::e_verNo, realProperty);
	//std::cout << "realProperty = " << realProperty << std::endl;
	BOOST_CHECK(property == realProperty);

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

BOOST_AUTO_TEST_CASE(CheckIsLeaf)
{
	std::string uri = "CheckIsLeaf/Node1/Node2";
	fs::path path(NS_DM_Client::NS_DataStorage::GetBasePath() + (NS_DM_Client::String)"/"
	    + c_testProfile + (NS_DM_Client::String)"/" + uri, fs::native);

	NS_DM_Client::Node node(uri, S_dataStorage);
	std::string property("node");
	node.SetProperty(NS_DM_Client::e_format, property.c_str());
	BOOST_CHECK(fs::exists(path));
	BOOST_CHECK(!node.IsLeaf());
	fs::remove_all(path.parent_path());

	NS_DM_Client::Node leaf(uri, S_dataStorage);
	property = "chr";
	node.SetProperty(NS_DM_Client::e_format, property.c_str());
	BOOST_CHECK(fs::exists(path));
	BOOST_CHECK(node.IsLeaf());

    fs::remove_all(NS_DM_Client::NS_DataStorage::GetBasePath());
}
//-------------------------------------------------------------------------------------------
// TODO: add test GetUnexistingProperty
BOOST_AUTO_TEST_CASE(GetNodeChildrenList)
{
	std::string uri1 = "GetNodeChildrenList/Node1/Node1_1";
	std::string uri2 = "GetNodeChildrenList/Node1/Node1_2";
	NS_DM_Client::Node node1(uri1, S_dataStorage);
	NS_DM_Client::Node node2(uri2, S_dataStorage);
	fs::path path1(NS_DM_Client::NS_DataStorage::GetBasePath() + (NS_DM_Client::String)"/"
	    + c_testProfile + (NS_DM_Client::String)"/" + uri1);
	fs::path path2(NS_DM_Client::NS_DataStorage::GetBasePath() + (NS_DM_Client::String)"/"
	    + c_testProfile + (NS_DM_Client::String)"/" + uri2);

	// create property to force saving to storage
	node1.SetProperty(NS_DM_Client::e_verNo, "version1");
	node2.SetProperty(NS_DM_Client::e_verNo, "version1");
	BOOST_CHECK(fs::exists(path1));
	BOOST_CHECK(fs::exists(path2));

	NS_DM_Client::Node::ChildrenPaths expectedChildrenPaths;
	expectedChildrenPaths.push_back("Node1_1");
	expectedChildrenPaths.push_back("Node1_2");
	NS_DM_Client::Node::ChildrenPaths realChildrenPaths;
	NS_DM_Client::Node parentNode("GetNodeChildrenList/Node1", S_dataStorage);
	parentNode.GetChildren(realChildrenPaths);
	//std::cout << "realChildren = " << realChildrenPaths[0] << " " << realChildrenPaths[1] << std::endl;
	BOOST_CHECK((expectedChildrenPaths[0] == realChildrenPaths[0]) || (expectedChildrenPaths[0] == realChildrenPaths[1])
		|| (expectedChildrenPaths[1] == realChildrenPaths[1]) || (expectedChildrenPaths[1] == realChildrenPaths[0]));

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


