// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "Configurator.hpp"
#include "Debug.hpp"

#include <algorithm>
#include <fstream>
#include <istream>
#include <sstream>

namespace {
inline std::string trimSpaces(const std::string &str)
{
	std::string trimmed = str;
	trimmed.erase(trimmed.begin(), std::find_if(trimmed.begin(), trimmed.end(), [](unsigned char c) {
		              return !std::isspace(c);
	              }));
	trimmed.erase(std::find_if(trimmed.rbegin(), trimmed.rend(), [](unsigned char c) {
		              return !std::isspace(c);
	              }).base(),
	              trimmed.end());
	return trimmed;
}
}  // namespace

namespace sw {

Configurator::Configurator(const std::string &filePath)
{
	std::fstream file(filePath, std::ios::in);
	if(file.fail())
	{
		return;
	}
	readConfiguration(file);
	file.close();
}

Configurator::Configurator(std::istream &str)
{
	readConfiguration(str);
}

bool Configurator::readConfiguration(std::istream &str)
{
	std::string line;
	std::string sectionName;

	int lineNumber = 0;
	while(getline(str, line))
	{
		++lineNumber;
		if(line.length())
		{
			if(line[line.length() - 1] == '\r')
			{
				line = line.substr(0, line.length() - 1);
			}

			if(!isprint(line[0]))
			{
				sw::warn("Cannot parse line %d of configuration, skipping line\n", lineNumber);
				return false;
			}

			std::string::size_type pLeft = line.find_first_of(";#[=");

			if(pLeft != std::string::npos)
			{
				switch(line[pLeft])
				{
				case '[':
					{
						std::string::size_type pRight = line.find_last_of("]");

						if(pRight != std::string::npos && pRight > pLeft)
						{
							sectionName = trimSpaces(line.substr(pLeft + 1, pRight - pLeft - 1));
							if(!sectionName.length())
							{
								sw::warn("Found empty section name at line %d of configuration\n", lineNumber);
							}
						}
					}
					break;
				case '=':
					{
						std::string key = trimSpaces(line.substr(0, pLeft));
						std::string value = trimSpaces(line.substr(pLeft + 1));
						if(!key.length() || !value.length())
						{
							sw::warn("Cannot parse key-value pair at line %d of configuration (key or value is empty), skipping key-value pair\n", lineNumber);
						}
						else
						{
							sections[sectionName].keyValuePairs[key] = value;
						}
					}
					break;
				case ';':
				case '#':
					// Ignore comments
					break;
				}
			}
		}
	}

	return sections.size() > 0;
}

void Configurator::writeFile(const std::string &filePath, const std::string &title)
{
	std::fstream file(filePath, std::ios::out);
	if(file.fail())
	{
		return;
	}

	file << "; " << title << std::endl
	     << std::endl;

	for(const auto &[sectionName, section] : sections)
	{
		file << "[" << sectionName << "]" << std::endl;
		for(const auto &[key, value] : section.keyValuePairs)
		{
			file << key << "=" << value << std::endl;
		}
		file << std::endl;
	}

	file.close();
}

std::optional<std::string> Configurator::getValueIfExists(const std::string &sectionName, const std::string &keyName) const
{
	const auto section = sections.find(sectionName);
	if(section == sections.end())
	{
		return std::nullopt;
	}

	const auto keyValue = section->second.keyValuePairs.find(keyName);
	if(keyValue == section->second.keyValuePairs.end())
	{
		return std::nullopt;
	}

	return keyValue->second;
}

std::string Configurator::getValue(const std::string &sectionName, const std::string &keyName, const std::string &defaultValue) const
{
	const auto value = getValueIfExists(sectionName, keyName);
	if(value)
	{
		return *value;
	}
	return defaultValue;
}

void Configurator::addValue(const std::string &sectionName, const std::string &keyName, const std::string &value)
{
	sections[sectionName].keyValuePairs[keyName] = value;
}

int Configurator::getInteger(const std::string &sectionName, const std::string &keyName, int defaultValue) const
{
	auto strValue = getValueIfExists(sectionName, keyName);
	if(!strValue)
	{
		return defaultValue;
	}

	std::stringstream ss{ *strValue };
	if(strValue->find("0x") != std::string::npos)
	{
		ss >> std::hex;
	}

	int val = 0;
	ss >> val;
	return val;
}

bool Configurator::getBoolean(const std::string &sectionName, const std::string &keyName, bool defaultValue) const
{
	auto strValue = getValueIfExists(sectionName, keyName);
	if(!strValue)
	{
		return defaultValue;
	}

	std::stringstream ss{ *strValue };

	bool val;
	ss >> val;
	if(ss.fail())
	{
		// Accept "true" and "false" as well.
		ss.clear();
		ss >> std::boolalpha >> val;
	}
	return val;
}

double Configurator::getFloat(const std::string &sectionName, const std::string &keyName, double defaultValue) const
{
	auto strValue = getValueIfExists(sectionName, keyName);
	if(!strValue)
	{
		return defaultValue;
	}

	std::stringstream ss{ *strValue };

	double val = 0;
	ss >> val;
	return val;
}
}  // namespace sw
