using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace VisimBox
{
    /// <summary>
    /// String parser helper object
    /// </summary>
    public class StringParser
    {
        #region Fields

        protected string BasicString;
        protected string[] _Words;
        protected char[] Delimiter;
        
        public CultureInfo cf;

        /// <summary>
        /// Number of words in string
        /// </summary>
        public int WordCount { get { return _Words.Length; } }

        public string this[int index]
        {
            get
            {
                if (index >= _Words.Length)
                    return null;
                return _Words[index];               
            }
        }


        #endregion

        #region Constructors

        /// <summary>
        /// No default constructor allowed
        /// </summary>
        protected StringParser()
        {
        }

        /// <summary>
        /// String parser from string, using ' ' as delimiter
        /// </summary>
        /// <param name="str">Source string</param>
        public StringParser(string str, CultureInfo cff)
        {
            BasicString = str;
            Delimiter = new char[1];
            Delimiter[0] = ' ';
            Parse();
            cf = cff;
        }

        /// <summary>
        /// String parser from string, using ' ' as delimiter
        /// </summary>
        /// <param name="str">Source string</param>
        public StringParser(string str) : this(str, null as CultureInfo)
        {
        }

        /// <summary>
        /// String parser from string with special delimiter
        /// </summary>
        /// <param name="str">Source string</param>
        /// <param name="delimiter">char delimiter</param>
        public StringParser(string str, char delimiter)
        {
            BasicString = str;
            Delimiter = new char[1];
            Delimiter[0] = delimiter;
            Parse();
            cf = null;
        }

        /// <summary>
        /// String parser from string with array of delimiters
        /// </summary>
        /// <param name="str">source string</param>
        /// <param name="delimiters">Delimiter array</param>
        public StringParser(string str, char[] delimiters)
        {
            BasicString = str;
            Delimiter = delimiters;
            Parse();
        }

        #endregion


        #region Privates

        bool IsDelimiter(char c)
        {
            for (int i = 0; i < Delimiter.Length; i++)
            {
                if (Delimiter[i] == c)
                    return true;
            }
            return false;
        }


        void Parse()
        {
            int count = 0;
            string str = BasicString;
            while (true)
            {
                int idx = str.IndexOfAny(Delimiter);
                if (idx == -1)
                    break;
                if (idx == str.Length - 1)
                    break;
                while (IsDelimiter(str[idx]) && (idx < str.Length))
                    idx++;
                count++;
                if (idx > (str.Length - 1))
                    break;
                str = str.Substring(idx);
            }
            if (count == 0)
            {
                _Words = new string[1];
                _Words[0] = BasicString;
                return;
            }

            count++;
            _Words = new string[count];

            str = BasicString;
            for (int i = 0; i < _Words.Length; i++)
            {
                int idx = str.IndexOfAny(Delimiter);
                if (idx == -1)
                {
                    _Words[i] = str;
                    break;
                }
                _Words[i] = str.Substring(0, idx);
                while (IsDelimiter(str[idx]) && (idx < str.Length))
                    idx++;
                if (idx > (str.Length - 1))
                    break;
                str = str.Substring(idx);
            }
        }

        #endregion


        /// <summary>
        /// Returns word with specified index
        /// </summary>
        /// <param name="idx">required index</param>
        /// <returns>Word or null if index out of range</returns>
        public string GetWord(int idx)
        {
            return this[idx];
        }

        /// <summary>
        /// Returns true if word on index is float
        /// </summary>
        /// <param name="idx">required index</param>
        /// <returns>True if float</returns>
        public bool IsFloat(int idx)
        {
            if (idx >= _Words.Length)
                return false;
            try
            {
                float d;
                if (cf != null)
                    d = (float)Convert.ToDouble(_Words[idx], cf);
                else d = (float)Convert.ToDouble(_Words[idx]);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Returns true if word on index is integer
        /// </summary>
        /// <param name="idx">required index</param>
        /// <returns>True if integer</returns>
        public bool IsInteger(int idx)
        {
            if (idx >= _Words.Length)
                return false;
            try
            {
                int d;
                if (cf != null)
                    d = Convert.ToInt32(_Words[idx], cf);
                else
                    d = Convert.ToInt32(_Words[idx]);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Returns float value of word on specified index
        /// </summary>
        /// <param name="idx">required index</param>
        /// <returns>float value or float.NaN</returns>
        public float GetFloat(int idx)
        {
            if (idx >= _Words.Length)
                return float.NaN;
            try
            {
                float d;
                if (cf != null)
                    d = (float)Convert.ToDouble(_Words[idx], cf);
                else d = (float)Convert.ToDouble(_Words[idx]);
                return d;
            }
            catch
            {
                return float.NaN;
            }
        }

        /// <summary>
        /// Returns integer value of word on specified index
        /// </summary>
        /// <param name="idx">required index</param>
        /// <returns>integer value or 0 if not integer</returns>
        public int GetInteger(int idx)
        {
            if (idx >= _Words.Length)
                return 0;
            try
            {
                int d;
                if (cf != null) d = Convert.ToInt32(_Words[idx], cf);
                else d = Convert.ToInt32(_Words[idx]);
                return d;
            }
            catch
            {
                return 0;
            }
        }

    }
}
