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

using namespace std;

#include <stdio.h>
#include <stdarg.h>
#include <ctype.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;
	}
}
