// SwiftShader Software Renderer
//
// Copyright(c) 2005-2012 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//

#include "Configurator.hpp"

#include <iostream>
#include <fstream>

using namespace std;

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

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

		readFile();
	}

	Configurator::~Configurator()
	{
	}

	bool Configurator::readFile()
	{
		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)
	{
		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);
		bool create = true;

		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;
	}
}
