using System;
using System.IO;
using System.Collections;
using System.Collections.Specialized;

namespace Icarus.Resources
{
	/// <summary>
	/// The Config Parser will parse a config file of the following format:
	/// 
	/// # This is a comment
	/// variable: value
	/// variable: value
	/// variable: value
	/// 
	/// </summary>
	public class ConfigParser
	{
        #region Declarations
		private IDictionary mVariables;
        #endregion

        #region Constructors

        /// <summary>
        /// Generate a new ConfigParser
        /// </summary>
        /// <param name="fileName">The configuration file to parse</param>
		public ConfigParser(string fileName)
		{
			mVariables = new ListDictionary();
			this.ParseConfigFile(fileName);
		}

        #endregion

		#region Public Functions
		/// <summary>
		/// Gets or sets configuration properties.
		/// </summary>
		public string this [string key]
		{
			get
			{
				return (string) mVariables[key];
			}
			set
			{
				mVariables[key] = value;
			}
		}
		#endregion

		#region Private Parts
		/// <summary>
		/// Parses the configuration file.
		/// </summary>
		/// <param name="filename"></param>
		private void ParseConfigFile(string filename)
		{
			StreamReader reader = new StreamReader(filename);
			Vcombo combo = nextVcombo(reader);

			while (combo != null)
			{
				this[combo.Name] = combo.Value;

				combo = nextVcombo(reader);
			}
		}

		/// <summary>
		/// Retrieve the next Vcombo object
		/// </summary>
		/// <returns>The next Vcombo, null if there is none</returns>
		private Vcombo nextVcombo(StreamReader reader) 
		{
			string s = nextLine(reader);
			string name;

			if (s == null) 
			{
				return null;
			}

			name = s.Substring(0, s.IndexOf(':')).Trim();

			s = s.Substring(s.IndexOf(':') + 1);
			s = s.Trim();

			return new Vcombo(name, s);
		}

		/// <summary>
		/// Retrieve the next line, automagically skips the comments
		/// </summary>
		/// <returns>The next non-comment line, null if there is none</returns>
		private string nextLine(StreamReader reader) 
		{
			string s;

			while (true) 
			{
				s = reader.ReadLine();
                
				if (s == null) 
				{
					return null;
				} 
				else 
				{
					s = s.Trim();

					if (s.Length == 0) 
					{
						continue;
					} 
					else if (s[0] != '#') 
					{
						break;
					}
				}
			}

			return s;
		}

		/// <summary>
		/// This stores a variable/value combination as generated by
		/// the ConfigParser class.
		/// </summary>
		private class Vcombo
		{
			#region Declarations
			private string sName;
			private string sValue;
			#endregion

			#region Constructors
			/// <summary>
			/// Generate a new Vcombo with fields as defined
			/// in the parameter list
			/// </summary>
			/// <param name="name">The variable name</param>
			/// <param name="val">The variable value</param>
			public Vcombo(string name, string val)
			{
				this.sName = name;
				this.sValue = val;
			}
			#endregion

			#region Fields
			/// <summary>
			/// This stores the variable name in string Representaton
			/// 
			/// The variable name is everything before the first ":"
			/// 
			/// Example:
			/// Stinkyness: -50
			/// 
			/// Variable is the string "Strinkyness"
			/// 
			/// </summary>
			public string Name
			{
				get { return this.sName; }
			}

			/// <summary>
			/// The value of the variable in a string Representation
			/// 
			/// This contains everything after the first ":" not including
			/// whitespace.
			/// 
			/// Example:
			/// Stinkyness:-50
			/// Stinkyness:          -50
			/// Stinkyness: -50
			/// 
			/// All have a value of the string "-50"
			/// 
			/// Example:
			/// PATH: C:\My Stuff\Video Games\SuperCool
			/// 
			/// Has a value of the string: "C:\My Stuff\Video Games\SuperCool"
			/// </summary>
			public string Value
			{ 
				get { return this.sValue; }
			}
			#endregion
		}
		#endregion
	}
}
