// 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 <fstream>
#include <iostream>

using namespace std;

#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#if defined(__unix__)
#	include <unistd.h>
#endif

namespace sw {

Configurator::Configurator(string iniPath)
{
	path = iniPath;

	readFile();
}

Configurator::~Configurator()
{
}

bool Configurator::readFile()
{
#if defined(__unix__)
	if(access(path.c_str(), R_OK) != 0)
	{
		return false;
	}
#endif

	fstream file(path.c_str(), ios::in);
	if(file.fail()) return false;

	string line;
	string keyName;

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

			if(!isprint(line[0]))
			{
				//	printf("Failing on char %d\n", line[0]);
				file.close();
				return false;
			}

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

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

						if(pRight != string::npos && pRight > pLeft)
						{
							keyName = line.substr(pLeft + 1, pRight - pLeft - 1);
							addKeyName(keyName);
						}
					}
					break;
				case '=':
					{
						string valueName = line.substr(0, pLeft);
						string value = line.substr(pLeft + 1);
						addValue(keyName, valueName, value);
					}
					break;
				case ';':
				case '#':
					// Ignore comments
					break;
				}
			}
		}
	}

	file.close();

	if(names.size())
	{
		return true;
	}

	return false;
}

void Configurator::writeFile(std::string title)
{
#if defined(__unix__)
	if(access(path.c_str(), W_OK) != 0)
	{
		return;
	}
#endif

	fstream file(path.c_str(), ios::out);
	if(file.fail()) return;

	file << "; " << title << endl
	     << endl;

	for(unsigned int keyID = 0; keyID < sections.size(); keyID++)
	{
		file << "[" << names[keyID] << "]" << endl;

		for(unsigned int valueID = 0; valueID < sections[keyID].names.size(); valueID++)
		{
			file << sections[keyID].names[valueID] << "=" << sections[keyID].values[valueID] << endl;
		}

		file << endl;
	}

	file.close();
}

int Configurator::findKey(string keyName) const
{
	for(unsigned int keyID = 0; keyID < names.size(); keyID++)
	{
		if(names[keyID] == keyName)
		{
			return keyID;
		}
	}

	return -1;
}

int Configurator::findValue(unsigned int keyID, string valueName) const
{
	if(!sections.size() || keyID >= sections.size())
	{
		return -1;
	}

	for(unsigned int valueID = 0; valueID < sections[keyID].names.size(); ++valueID)
	{
		if(sections[keyID].names[valueID] == valueName)
		{
			return valueID;
		}
	}

	return -1;
}

unsigned int Configurator::addKeyName(string keyName)
{
	names.resize(names.size() + 1, keyName);
	sections.resize(sections.size() + 1);
	return (unsigned int)names.size() - 1;
}

void Configurator::addValue(string const keyName, string const valueName, string const value)
{
	int keyID = findKey(keyName);

	if(keyID == -1)
	{
		keyID = addKeyName(keyName);
	}

	int valueID = findValue(keyID, valueName);

	if(valueID == -1)
	{
		sections[keyID].names.resize(sections[keyID].names.size() + 1, valueName);
		sections[keyID].values.resize(sections[keyID].values.size() + 1, value);
	}
	else
	{
		sections[keyID].values[valueID] = value;
	}
}

string Configurator::getValue(string keyName, string valueName, string defaultValue) const
{
	int keyID = findKey(keyName);
	if(keyID == -1) return defaultValue;
	int valueID = findValue((unsigned int)keyID, valueName);
	if(valueID == -1) return defaultValue;

	return sections[keyID].values[valueID];
}

int Configurator::getInteger(string keyName, string valueName, int defaultValue) const
{
	char svalue[256];

	sprintf(svalue, "%d", defaultValue);

	return atoi(getValue(keyName, valueName, svalue).c_str());
}

bool Configurator::getBoolean(string keyName, string valueName, bool defaultValue) const
{
	return getInteger(keyName, valueName, (int)defaultValue) != 0;
}

double Configurator::getFloat(string keyName, string valueName, double defaultValue) const
{
	char svalue[256];

	sprintf(svalue, "%f", defaultValue);

	return atof(getValue(keyName, valueName, svalue).c_str());
}

unsigned int Configurator::getFormatted(string keyName, string valueName, char *format,
                                        void *v1, void *v2, void *v3, void *v4,
                                        void *v5, void *v6, void *v7, void *v8,
                                        void *v9, void *v10, void *v11, void *v12,
                                        void *v13, void *v14, void *v15, void *v16)
{
	string value = getValue(keyName, valueName);

	if(!value.length()) return false;

	unsigned int nVals = sscanf(value.c_str(), format,
	                            v1, v2, v3, v4, v5, v6, v7, v8,
	                            v9, v10, v11, v12, v13, v14, v15, v16);

	return nVals;
}

}  // namespace sw
