#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <direct.h>
#include <stdlib.h>
#include <vector>
#include "windows.h"

#define SCREEN_DIVIDER		3
#define SCREEN_OFFSET_X		800 / SCREEN_DIVIDER + 1


// Field strcture
typedef struct
{
	std::string label;
	float value;
} FIELDS_T;

// Tag structure with multiple fields
typedef struct  
{
	std::string Obj_Parent;
	std::vector<FIELDS_T> fields;
}TAG_T;

// File with multiple tags with multiple fields
typedef struct 
{
	std::string filename;
	std::vector<TAG_T> tags;
} EXCEPTIONS_T;

static std::string m_xmlFile;
static std::vector<EXCEPTIONS_T> m_exceptions;
static std::string m_currentParant;
static void ExceptionsDefinitionsInit();

static std::string GetPath()
{
	char buffer[MAX_PATH];
	GetModuleFileName(NULL, buffer, MAX_PATH);
	std::string::size_type pos = std::string(buffer).find_last_of("\\/");
	return std::string(buffer).substr(0, pos);
}
// -----------------------------------------------------------------------------------

int main(int argc, char** argv)
{	
	ExceptionsDefinitionsInit();

	printf("Welcome to Star Wars: Knights Of The Old Republic II: The Sith Lords - Surround/Eyefinity HUD Converver\n");
	printf("Helifax 2015\n\n");

	if (argc == 1)
	{
		printf("Input File not specified\n");
		system("pause");
		return -1;
	}

	m_xmlFile = argv[1];
	std::string inputFileName = GetPath() + "\\Output\\" + argv[1];
	printf("Input file is: %s", inputFileName.c_str());
	std::stringstream buffer;

	std::string dirToMake = GetPath() + "/Output";
	_mkdir(dirToMake.c_str());
	dirToMake = GetPath() + "/Override";
	_mkdir(dirToMake.c_str());

	std::fstream configFile(inputFileName, std::fstream::in);
	if (configFile.is_open())
	{
		for (std::string configLine; getline(configFile, configLine);)
		{
			// Find the current Parent and keep it
			if (configLine.find("Label=\"TAG\"") != std::string::npos)
			{
				size_t position = 0;
				if ((position = configLine.find("Value")) != std::string::npos)
				{
					m_currentParant = configLine.substr(position + 7);
				}
			}

			// Find our values
			if (configLine.find("Label=\"LEFT\"") != std::string::npos)
			{
				size_t position = 0;
				if ((position = configLine.find("Value")) != std::string::npos)
				{
					bool valueFound = false;
					float valueToUse = 0;
					for (size_t x = 0; x < m_exceptions.size(); x++)
					{
						if (m_xmlFile == m_exceptions[x].filename)
						{
							for (size_t i = 0; i < m_exceptions[x].tags.size(); i++)
							{
								// We have found our parent
								if (m_currentParant.find(m_exceptions[x].tags[i].Obj_Parent) != std::string::npos)
								{
									for (size_t j = 0; j < m_exceptions[x].tags[i].fields.size(); j++)
									{
										// Do we have this label ? 
										if (configLine.find(m_exceptions[x].tags[i].fields[j].label) != std::string::npos)
										{
											// found
											valueFound = true;
											valueToUse = m_exceptions[x].tags[i].fields[j].value;
											break;
										}
										if (valueFound)
										{
											break;
										}
									}
								}
								if (valueFound)
								{
									break;
								}
							}
							if (valueFound)
							{
								break;
							}
						}
					}
					std::string value = configLine.substr(position + 7);
					// Read the depth hack
					int LeftValue = std::stoi(value, 0);
					if (LeftValue > 0) 
					{
						// if we don't have it as an exception do the magic
						if (!valueFound)
						{
							LeftValue /= SCREEN_DIVIDER;
							LeftValue += SCREEN_OFFSET_X;
						}
						else
						{
							LeftValue /= SCREEN_DIVIDER;
							LeftValue += (int)valueToUse;
						}
						char temp[50];
						sprintf_s(temp, "%d", LeftValue);
						configLine.insert(position + 7, temp);
						configLine.replace(position + 7 + strlen(temp), 100, "\" />");
					}
					// Add it to the buffer
					buffer << configLine;
				}
			}
			else if (configLine.find("Label=\"WIDTH\"") != std::string::npos)
			{
				size_t position = 0;
				if ((position = configLine.find("Value")) != std::string::npos)
				{
					bool valueFound = false;
					float valueToUse = 0;
					for (size_t x = 0; x < m_exceptions.size(); x++)
					{
						if (m_xmlFile == m_exceptions[x].filename)
						{
							for (size_t i = 0; i < m_exceptions[x].tags.size(); i++)
							{
								// We have found our parent
								if (m_currentParant.find(m_exceptions[x].tags[i].Obj_Parent) != std::string::npos)
								{
									for (size_t j = 0; j < m_exceptions[x].tags[i].fields.size(); j++)
									{
										// Do we have this label ? 
										if (configLine.find(m_exceptions[x].tags[i].fields[j].label) != std::string::npos)
										{
											// found
											valueFound = true;
											valueToUse = m_exceptions[x].tags[i].fields[j].value;
											break;
										}
										if (valueFound)
										{
											break;
										}
									}
								}
								if (valueFound)
								{
									break;
								}
							}
							if (valueFound)
							{
								break;
							}
						}
					}
					// if we don't have it as an exception do the magic
					std::string value = configLine.substr(position + 7);
					// Read the depth hack
					int LeftValue = std::stoi(value, 0);
					if (LeftValue != 800)
					{
						// if we don't have it as an exception do the magic
						if (!valueFound)
						{
							LeftValue /= SCREEN_DIVIDER;
						}
						else
						{
							LeftValue /= SCREEN_DIVIDER;
							float temp = LeftValue * valueToUse;
							LeftValue = (int)temp;
						}
						char temp[50];
						sprintf_s(temp, "%d", LeftValue);
						configLine.insert(position + 7, temp);
						configLine.replace(position + 7 + strlen(temp), 100, "\" />");
					}
					// Add it to the buffer
					buffer << configLine;
				}
			}
			else
			{
				buffer << configLine;
			}
			buffer << std::endl;
		}
		configFile.close();

		/* Write the whole stringstream back to the file */
		configFile.open(inputFileName, std::fstream::out);
		configFile << buffer.str();
		configFile.close();
	}
	else
	{
		printf("Cannot open Input file %s", inputFileName.c_str());
	}
	return 0;
}

// -----------------------------------------------------------------------------------


static void ExceptionsDefinitionsInit()
{
	{
		TAG_T newTag;
		FIELDS_T newField;
		EXCEPTIONS_T exceptions;
		exceptions.filename = "confirm_p.gui.xml";
		newTag.Obj_Parent = "LB_MESSAGE";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.resize(0);
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);
		m_exceptions.push_back(exceptions);
	}
	//////////////////////////////////////////////////////////////////////////
	{
	TAG_T newTag;
	FIELDS_T newField;
	EXCEPTIONS_T exceptions;
	// New File
	exceptions.filename = "container_p.gui.xml";
	newTag.Obj_Parent = "LB_ITEMS";
	newField.label = "LEFT";
	newField.value = 0;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);

	//////////////////////////////////////////////////////////////////////////

	newTag.fields.resize(0);
	newTag.Obj_Parent = "LBL_MESSAGE";
	newField.label = "LEFT";
	newField.value = 0;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);

	//////////////////////////////////////////////////////////////////////////

	newTag.fields.resize(0);
	newTag.Obj_Parent = "PROTOITEM";
	newField.label = "LEFT";
	newField.value = 0;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);


	//////////////////////////////////////////////////////////////////////////

	newTag.fields.resize(0);
	newTag.Obj_Parent = "SCROLLBAR";
	newField.label = "LEFT";
	newField.value = 1;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);


	//////////////////////////////////////////////////////////////////////////

	newTag.fields.resize(0);
	newTag.Obj_Parent = "BTN_OK";
	newField.label = "LEFT";
	newField.value = 0;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);

	//////////////////////////////////////////////////////////////////////////
	
	newTag.fields.resize(0);
	newTag.Obj_Parent = "BTN_GIVEITEMS";
	newField.label = "LEFT";
	newField.value = 0;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);

	//////////////////////////////////////////////////////////////////////////

	newTag.fields.resize(0);
	newTag.Obj_Parent = "BTN_CANCEL";
	newField.label = "LEFT";
	newField.value = 0;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);

	m_exceptions.push_back(exceptions);
}
//////////////////////////////////////////////////////////////////////////
	{
		TAG_T newTag;
		FIELDS_T newField;
		EXCEPTIONS_T exceptions;
		exceptions.filename = "mipc28x6_p.gui.xml";
		newTag.Obj_Parent = "LBL_TARGET";
		newField.label = "LEFT";
		newField.value = 0;
		newTag.fields.push_back(newField);

		// Store them
		exceptions.tags.push_back(newTag);

		newTag.fields.resize(0);
		newTag.Obj_Parent = "BTN_TARGET";
		newField.label = "LEFT";
		newField.value = 0;
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		m_exceptions.push_back(exceptions);

	}
//////////////////////////////////////////////////////////////////////////
	{
	TAG_T newTag;
	FIELDS_T newField;
	EXCEPTIONS_T exceptions;
	exceptions.filename = "pause_p.gui.xml";
	newTag.Obj_Parent = "LBL_PAUSEREASON";
	newField.label = "LEFT";
	newField.value = 0;
	newTag.fields.push_back(newField);

	// Store them
	exceptions.tags.push_back(newTag);

	newTag.fields.resize(0);
	newTag.Obj_Parent = "LBL_PRESS";
	newField.label = "LEFT";
	newField.value = 0;
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);

	newTag.fields.resize(0);
	newTag.Obj_Parent = "TGuiPanel";
	newField.label = "LEFT";
	newField.value = 0;
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);
	

	m_exceptions.push_back(exceptions);

}
//////////////////////////////////////////////////////////////////////////
	{
		TAG_T newTag;
		FIELDS_T newField;
		EXCEPTIONS_T exceptions;
		// New File
		exceptions.filename = "skillinfo_p.gui.xml";
		newTag.Obj_Parent = "LB_ITEMS";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////

		newTag.fields.resize(0);
		newTag.Obj_Parent = "LBL_MESSAGE";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////

		newTag.fields.resize(0);
		newTag.Obj_Parent = "PROTOITEM";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);


		//////////////////////////////////////////////////////////////////////////

		newTag.fields.resize(0);
		newTag.Obj_Parent = "SCROLLBAR";
		newField.label = "LEFT";
		newField.value = 1;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);


		//////////////////////////////////////////////////////////////////////////

		newTag.fields.resize(0);
		newTag.Obj_Parent = "BTN_OK";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////

		newTag.fields.resize(0);
		newTag.Obj_Parent = "LB_SKILLS";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////

		m_exceptions.push_back(exceptions);
	}

	{
	TAG_T newTag;
	FIELDS_T newField;
	EXCEPTIONS_T exceptions;
	// New File
	exceptions.filename = "map_p.gui.xml";
	newTag.Obj_Parent = "LBL_Map";
	newField.label = "LEFT";
	newField.value = 60;

	// Store them
	newTag.fields.push_back(newField);
	newField.label = "WIDTH";
	newField.value = 3;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);

	//////////////////////////////////////////////////////////////////////////

	newTag.fields.resize(0);
	newTag.Obj_Parent = "LBL_Area";
	newField.label = "LEFT";
	newField.value = 60;

	// Store them
	newTag.fields.push_back(newField);
	newField.label = "WIDTH";
	newField.value = 1;

	// Store them
	newTag.fields.push_back(newField);
	exceptions.tags.push_back(newTag);

	
	m_exceptions.push_back(exceptions);

}
//////////////////////////////////////////////////////////////////////////
	{
		TAG_T newTag;
		FIELDS_T newField;
		EXCEPTIONS_T exceptions;
		// New File
		exceptions.filename = "gameover_p.gui.xml";
		newTag.Obj_Parent = "BTN_LASTSAVE";
		newField.label = "LEFT";
		newField.value = 00;

		// Store them
		newTag.fields.push_back(newField);
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////

		newTag.fields.resize(0);
		newTag.Obj_Parent = "BTN_LOADGAME";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////

		newTag.fields.resize(0);
		newTag.Obj_Parent = "BTN_QUIT";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////

		newTag.fields.resize(0);
		newTag.Obj_Parent = "LBL_MESSAGE";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);


		m_exceptions.push_back(exceptions);
	}
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	{
		TAG_T newTag;
		FIELDS_T newField;
		EXCEPTIONS_T exceptions;
		// New File
		exceptions.filename = "pwrlvlup_p.gui.xml";
		newTag.Obj_Parent = "LB_POWERS";
		newField.label = "LEFT";
		newField.value = 106;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////
		newTag.fields.resize(0);
		newTag.Obj_Parent = "LB_POWERS";
		newField.label = "WIDTH";
		newField.value = 2.57f;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		m_exceptions.push_back(exceptions);
	}
	//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
	{
		TAG_T newTag;
		FIELDS_T newField;
		EXCEPTIONS_T exceptions;
		// New File
		exceptions.filename = "ftchrgen_p.gui.xml";
		newTag.Obj_Parent = "LB_FEATS";
		newField.label = "LEFT";
		newField.value = 106;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////
		newTag.fields.resize(0);
		newTag.Obj_Parent = "LB_FEATS";
		newField.label = "WIDTH";
		newField.value = 2.57f;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		m_exceptions.push_back(exceptions);
	}
//////////////////////////////////////////////////////////////////////////

	{
		TAG_T newTag;
		FIELDS_T newField;
		EXCEPTIONS_T exceptions;
		// New File
		exceptions.filename = "savename_p.gui.xml";
		newTag.Obj_Parent = "BTN_OK";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////
		newTag.fields.resize(0);
		newTag.Obj_Parent = "EDITBOX";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////
		newTag.fields.resize(0);
		newTag.Obj_Parent = "BTN_CANCEL";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////
		newTag.fields.resize(0);
		newTag.Obj_Parent = "LBL_TITLE";
		newField.label = "LEFT";
		newField.value = 0;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		m_exceptions.push_back(exceptions);
	}
	//////////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////////
	{
		TAG_T newTag;
		FIELDS_T newField;
		EXCEPTIONS_T exceptions;
		// New File
		exceptions.filename = "abilities_p.gui.xml";
		newTag.Obj_Parent = "LB_ABILITY";
		newField.label = "LEFT";
		newField.value = 106;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		//////////////////////////////////////////////////////////////////////////
		newTag.fields.resize(0);
		newTag.Obj_Parent = "LB_ABILITY";
		newField.label = "WIDTH";
		newField.value = 2.57f;

		// Store them
		newTag.fields.push_back(newField);
		exceptions.tags.push_back(newTag);

		m_exceptions.push_back(exceptions);
	}
}
// -----------------------------------------------------------------------------------