// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Implements system related functions
		\author Romain Behar (romainbehar@yahoo.com)
*/

#include "result.h"
#include "string_modifiers.h"
#include "system_functions.h"

#include <boost/filesystem/path.hpp>
#include <boost/tokenizer.hpp>

#include <sys/stat.h>

// Define some platform-specific odds-and-ends
#ifdef K3D_PLATFORM_IS_WIN32

#define SEARCHPATH_SEPARATOR_STRING ";"
#define DEFAULT_TEMP_DIRECTORY "c:\\"
#define DEFAULT_HOME_DIRECTORY "c:\\"
#include <io.h>

#else // K3D_PLATFORM_IS_WIN32

#define SEARCHPATH_SEPARATOR_STRING ":"
#define DEFAULT_TEMP_DIRECTORY "/tmp"
#define DEFAULT_HOME_DIRECTORY "/"

#endif // !K3D_PLATFORM_IS_WIN32


namespace k3d
{

namespace system
{

const std::string get_env(const std::string& EnvironmentVariable)
{
	const char* variable = getenv(EnvironmentVariable.c_str());
	if(variable)
		return std::string(variable);

	return std::string();
}

const boost::filesystem::path get_home_directory()
{
	static boost::filesystem::path home_directory;
	if(home_directory.empty())
		{
			if(getenv("HOME"))
				{
					home_directory = boost::filesystem::path(getenv("HOME"), boost::filesystem::native);
				}
			else
				{
					home_directory = boost::filesystem::path(DEFAULT_HOME_DIRECTORY, boost::filesystem::native);
					std::cerr << __PRETTY_FUNCTION__ << ": using default home directory [" << home_directory.native_file_string() << "]" << std::endl;
				}
		}

	return home_directory;
}

const boost::filesystem::path get_temp_directory()
{
	static boost::filesystem::path temp_directory;
	if(temp_directory.empty())
		{
			if(getenv("TMPDIR"))
				{
					temp_directory = boost::filesystem::path(getenv("TMPDIR"), boost::filesystem::native);
				}
			else if(getenv("TMP"))
				{
					temp_directory = boost::filesystem::path(getenv("TMP"), boost::filesystem::native);
				}
			else if(getenv("TEMP"))
				{
					temp_directory = boost::filesystem::path(getenv("TEMP"), boost::filesystem::native);
				}
			else
				{
					temp_directory = boost::filesystem::path(DEFAULT_TEMP_DIRECTORY, boost::filesystem::native);
				}
		}

	return temp_directory;
}

bool file_modification_time(const boost::filesystem::path& File, time_t& ModificationTime)
{
	struct stat statistics;
	if(-1 == stat(File.native_file_string().c_str(), &statistics))
		return false;

	ModificationTime = statistics.st_mtime;

	return true;
}

bool run_process(const std::string& CommandLine, std::ostream& Stream)
{
	// Sanity checks ...
	return_val_if_fail(CommandLine.size(), false);

	// Start the child process ...
	FILE* file = popen(CommandLine.c_str(), "r");
	return_val_if_fail(file, false);

	// Allocate a buffer for reading ...
	const unsigned long buffersize = 512;
	char* buffer = new char[buffersize+1];
	return_val_if_fail(buffer, false);

	// Read data from the pipe ...
	for(int bytesread = read(fileno(file), buffer, buffersize); bytesread > 0; bytesread = read(fileno(file), buffer, buffersize))
	{
		buffer[bytesread] = '\0';
		Stream << buffer;
	}

	// Delete the buffer ...
	delete[] buffer;
	return true;
}

void decompose_path_list(const std::string Input, paths_t& Output)
{
	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
	boost::char_separator<char> separator(SEARCHPATH_SEPARATOR_STRING);
	tokenizer input(Input, separator);

	for(tokenizer::iterator path = input.begin(); path != input.end(); ++path)
		{
			const std::string path_string = k3d::trim(*path);
			if(!path_string.empty())
				Output.push_back(boost::filesystem::path(path_string, boost::filesystem::native));
		}
}

} // namespace system

} // namespace k3d


