#include "miscFunctions.hpp"
#include <filesystem>
#include <optional>
#include <iostream>
#include <string>
#include <shlwapi.h>
#include <filesystem>
#include "cenos_exception.h"

#pragma comment(lib, "shlwapi.lib")

void misc::getdp_info()
{

	//because we are robbed of ENV, we have to set it, and it has to be at least `2` to get output from GetDP!

	//Temporal fix for CP-1511
	// if (!SetEnvironmentVariable("OPENBLAS_VERBOSE", TEXT("2")))  // original
	std::wstring wstr = L"OPENBLAS_VERBOSE";
	if (!SetEnvironmentVariable(wstr.c_str(), TEXT("2")))
	{
		std::string err_str = "SetEnvironmentVariable failed (" + std::to_string(GetLastError()) + ")\n";
		throw cenos_exception(err_str);
	}

	//getdp output is in stderr >:| so we have to redirect & take only relevant part from output.
	std::string  command = "getdp.exe -version 2>&1 | find \"Core\"";
	std::string result = "";

	char   psBuffer[128];
	FILE* pPipe;

	//open the pipe
	std::cout << "Opening pipe" << std::endl;
	if ((pPipe = _popen(command.c_str(), "rt")) == NULL) {
		throw cenos_exception("Error: Failed to Open GetDP pipe.\n");
	}

	//read data from pipe
	while (fgets(psBuffer, 128, pPipe))
		result += psBuffer;

	//close the pipe
	if (!feof(pPipe)) {
		throw cenos_exception("Error: Failed to Read GetDP pipe to the end.\n");
	}
		

	//replace std::endls with spaces : make pretty text
	std::replace(result.begin(), result.end(), '\n', ' ');

	//we want at least some indication of whats going on
	if (result.length() == 0) {
		result = "<no-info>";
	}
		

	std::cout << "GetDP CPU info : [ " << result << "]" << std::endl;
}

std::string misc::getPathExtension(std::string path)
{
	std::string extension = std::filesystem::path(path.c_str()).extension().string();
	return extension;
}

std::string misc::getFileName(std::string path)
{
	std::string extension = std::filesystem::path(path.c_str()).filename().string();
	return extension;
}

bool misc::fileExist(const std::string& fileName)
{
	struct stat buffer;
	return (stat(fileName.c_str(), &buffer) == 0);
}

void misc::createFolder(const std::string& path)
{
	std::filesystem::path resdir(path);
	std::error_code ec;
	if (!std::filesystem::exists(resdir, ec))
	{
		if (!std::filesystem::create_directory(resdir))
		{
			std::string message = "Could not create directory " + path;
			throw cenos_exception(message);
		}
	}
}

std::optional<std::string> misc::getCenosConfigDir()
{
	char const* tmp = getenv("CENOS_CONFIG");
	if (!tmp) {
		return {};
	}
	return tmp;
}

std::string misc::getCenosApp()
{
	char const* tmp = getenv("CENOS_APP");
	return tmp;
}

//check if TEMP already ends with 'cenos' : if it does, return only '\\'
static std::string temp_ends_with(std::string_view temp_path)
{
	std::string_view _cenos_ = "cenos";
	int found_at_end = temp_path.compare(temp_path.size() - _cenos_.size(), _cenos_.size(), _cenos_);
	return found_at_end == 0 ? "\\" : "\\cenos\\";
}

std::string misc::getLogPrefix()
{
	time_t t = time(0);
	struct tm* now = localtime(&t);

	std::stringstream month, date, hours, minutes, seconds;
	month << std::setw(2) << std::setfill('0') << (now->tm_mon + 1);
	date << std::setw(2) << std::setfill('0') << (now->tm_mday);

	//NEW                            check if \\cenos\\ has been supplied by Frontend !
	return std::string(getenv("TEMP")) + temp_ends_with(std::string(getenv("TEMP"))) + std::to_string(now->tm_year + 1900) + "-" + month.str() +
		"-" + date.str();
}

ryml::Tree misc::parseYaml(std::string filename) {
	std::ifstream yaml_stream(filename);
	std::stringstream buffer;

	if (!yaml_stream.is_open())
	{
		throw cenos_exception("Could not open file: " + filename);
	}

	// Check if yaml begins with "---", if so, skip that line
	std::string line;
	std::getline(yaml_stream, line);
	if (line.find("---") == std::string::npos) {
		// --- was not found, so we have to return back to the beginning of file
		yaml_stream.seekg(0);
	}

	buffer << yaml_stream.rdbuf();
	ryml::Tree tree = ryml::parse(c4::to_csubstr(buffer.str().c_str()));
	yaml_stream.close();
	return tree;
}
