using System.Collections.Generic;
using System.IO;
using System;

//Třída, která se stará o práci s ini souborem

public class IniReaderWriter
{
	private string inifileopened;														//string se jménem otevřeného souboru, včetně koncovky
	private List<IniReaderWriterSection> listofsections;		//Seznam sekcí


//----------------------------- Konstruktory --------------------------------------------

	//základní konstruktor
		public IniReaderWriter ()
		{
		inifileopened = null;
		listofsections = new List<IniReaderWriterSection>();
		}

	//Konstruktor s otevřením souboru
	public IniReaderWriter (string aFile)
	{
		inifileopened = null;
		listofsections = new System.Collections.Generic.List<IniReaderWriterSection>();

		ReadIniFile (aFile);																					//zavolat metodu na otevření souboru
	}


//----------------------------- Metody --------------------------------------------------------

	//náhražka za String.IsNullOrWhiteSpace, který je v nejnovější verzi .Net která tu není
	private bool ConsistsOfWhiteSpace(string s){
		foreach(char c in s){
			if(c != ' ') return false;
		}
		return true;
		
	} 


	//Přečte soubor
	public void ReadIniFile (string aFilePath)											//vraci true pokud soubor existuje
	{
			using (StreamReader IniStreamReader = new StreamReader(@aFilePath)) 		//otevře soubor pro čtení
			{
				inifileopened = aFilePath;														//uloží cestu k souboru, který byl napsoled přečten
				string loadedline;
				uint lineindex = 0;
				int sectionindex = -1;

				while ((loadedline = IniStreamReader.ReadLine()) != null) 				//čte řádky dokud nedojde na konec souboru
				{		
					lineindex++;

					if (ConsistsOfWhiteSpace(loadedline))								//zjistí, jestli string není prázdný řádek
						continue;
					else if (loadedline.Contains ("[") && loadedline.Contains ("]"))	//zjistí, jestli string obsahuje název sekce, ořeže ho a vloží do seznamu
					{
						IniReaderWriterSection newsection = new IniReaderWriterSection(loadedline.Substring(loadedline.IndexOf('[') + 1, loadedline.IndexOf(']') - loadedline.IndexOf('[') - 1));
						listofsections.Add(newsection);
						sectionindex++;
					}
					else
					{																	//rozdělí string podle znaku '=', zjistí jestli je tam jen jedno = a přidá do seznamu
						string[] splitedline;
						string[] splitstring = new string[] {"="};
						splitedline = loadedline.Split(splitstring, StringSplitOptions.RemoveEmptyEntries);
						
						if(splitedline.Length != 2)
						throw new InvalidIniDataException(String.Format("Invalid format of data on the line {0}.", lineindex));

						if(listofsections.Count == 0)
						throw new InvalidIniDataException(String.Format("Line {0} is not inside valid section.", lineindex));

						listofsections[sectionindex].AddKey(splitedline[0].Trim(), splitedline[1].Trim());
					}
				}
			}
	}


	//Projde seznam sekcí a klíčů a vrátí odpovídající hodnotu, pokud hledaný klíč neexistuje, vrátí null
	public string GetKeyValue(string aSection, string aKey)
	{
		foreach (IniReaderWriterSection section in listofsections) 
		{
			if (section.Title == aSection)
			{
				foreach (IniReaderWriterKey key in section.GetListOfKeys())
				{
					if (key.Key == aKey)
						return key.Value;
				}
			}
		}

		return null;
	}


	//vrátí cestu otevřeného souboru
	public string GetIniFileLoaded()
	{
		return inifileopened;
	}

	public string GetSectionName (int aNumber)
	{
		if(aNumber < listofsections.Count)
			return listofsections[aNumber].Title;
		else
			return null;
	}

	public int GetNumberOfSections ()
	{
		return listofsections.Count;
	}

	public int GetNumberOfKeysInSection (string aSection)
	{
		foreach (IniReaderWriterSection section in listofsections) 
		{
			if (section.Title == aSection)
			{
				return section.GetNumberOfKeys();
			}
		}
		return 0;
	}







	//Přidá novou sekci
	public void AddNewSection(string aSectionName)
	{
		IniReaderWriterSection newsection = new IniReaderWriterSection (aSectionName);
		listofsections.Add(newsection);
	}


	//Přidá nový klíč
	public void AddNewKey(string aSectionName, string aKeyName, string aKeyValue)
	{
		int index = -1;
		foreach (IniReaderWriterSection section in listofsections) 
		{
			index++;
			if (section.Title == aSectionName)
			{
				listofsections[index].AddKey (aKeyName, aKeyValue);
				return;
			}
		}

		throw new InvalidIniDataException(String.Format("Section {0} does not exist.", aSectionName));
	}


	//Změní hodnotu klíče
	public void ChangeKeyValue(string aSectionName, string aKeyName, string aKeyValue)
	{
		int index = -1;
		foreach (IniReaderWriterSection section in listofsections) 
		{
			index++;
			if (section.Title == aSectionName)
			{
				listofsections[index].ChangeKey(aKeyName, aKeyValue);
				return;
			}
		}
		
		throw new InvalidIniDataException(String.Format("Section {0} does not exist.", aSectionName));
	}


	//Přepsání ini souboru
	public void RewriteIniFile (string aFilePath)
	{
		using (StreamWriter IniStreamWriter = new StreamWriter(@aFilePath, false)) 
		{
			int index = -1;
			foreach (IniReaderWriterSection section in listofsections) 
			{
				index++;

				if (index != 0)
					IniStreamWriter.WriteLine ();

				IniStreamWriter.WriteLine (section.ToString());

				foreach (IniReaderWriterKey key in section.GetListOfKeys())
				{
					IniStreamWriter.WriteLine (key.ToString());
				}
			}
		}
	}





	//Vrátí, jestli je třída prázdná
	public bool CheckIfEmpty()
	{
		if (listofsections.Count == 0)
			return true;
		else
			return false;
	}


	//Vyprázdní třídu
	public void FlushIniData()
	{
		for (int index = listofsections.Count - 1; index >= 0; index--)
		{
			listofsections.RemoveAt(index);
		}
	}


	//Odstraní Sekci
	public void DeleteSection(string aSectionName)
	{
		int index = -1;
		foreach (IniReaderWriterSection section in listofsections) 
		{
			index++;
			if (section.Title == aSectionName)
			{
				listofsections.RemoveAt (index);
				return;
			}
		}
	}


	//Odstraní klíč v sekci
	public void DeleteKey(string aSectionName, string aKeyName)
	{
		int index = -1;
		foreach (IniReaderWriterSection section in listofsections) 
		{
			index++;
			if (section.Title == aSectionName)
			{
				listofsections[index].DeleteKey(aKeyName);
				return;
			}
		}
	}






	//Přepsání metody ToString, pokud je v inifileopened hodnota, vrátí ji, poud ne, vrátí None (žádný)
	public override string ToString ()
	{
		if (System.String.IsNullOrEmpty(inifileopened))
						return "None";
				else
						return inifileopened;
	}
}

