#include "pw/system/path.hpp"

#if defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
	#define WIN32_LEAN_AND_MEAN
	#include <windows.h>
	#include <tchar.h>
	#include <direct.h>
#elif defined(__APPLE__)
	#include <CoreFoundation/CoreFoundation.h>
	#include <unistd.h>
	#if defined(__MACH__)
		#include <mach/mach.h>
	#endif
//	#include "_host/helpers_osx.h"
#elif defined(__USE_POSIX)
	#include <unistd.h>
#else
	// Unknown platform
#endif

// Why? LLVM does not adhere to C++17
//#include <filesystem>

namespace pw {


struct path::impl {

	path &host;

	impl(path &host_) : host(host_) {}

};



//
//
//
path &path::get()
{
	static path instance;
	return instance;
}

path::~path()
{
}

std::string path::separator() const
{
#if defined(WIN32)
    return std::string("\\");
#else
	return std::string("/");
#endif
}

std::string path::executable_path() const
{
	std::string result;
	const size_t MAXPATHLEN = 2048;
	std::vector<char> buf(MAXPATHLEN);

#if defined(__APPLE__)

	CFBundleRef mainBundle = CFBundleGetMainBundle();
	CFURLRef bundleURL = CFBundleCopyExecutableURL(mainBundle);
	CFStringRef pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
	CFStringGetCString(pathStr, buf.data(), buf.size(), kCFStringEncodingASCII);

	CFRelease(pathStr);
	CFRelease(bundleURL);

#elif defined(_WIN32) || defined(_WIN64) || defined(_WIN32_WCE)
	static TCHAR lpFname[MAXPATHLEN];
	DWORD ret = GetModuleFileName( NULL, &lpFname[0], MAXPATHLEN );
	result.assign(&lpFname[0]);
#elif defined(__USE_POSIX)
    readlink("/proc/self/exe", buf.data(), buf.size());
#endif
	result.assign(buf.data());

	return result;
}

std::string path::find_file(const std::string&) const
{
    // TODO: Implement
    return std::string();
}

path::path()
{
	_impl = std::make_unique<impl>(*this);
}

std::string path::get_filename(const std::string& filepath,
							   bool with_extension) const
{
	std::size_t dotPos = filepath.rfind('.');
	std::size_t sepPos = filepath.rfind(separator());

	if(sepPos != std::string::npos) {
		return filepath.substr(sepPos + 1,
							   filepath.size() - (with_extension || dotPos != std::string::npos ? 1 : dotPos) );
	}
	return "";
}

}
