using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Globalization;

namespace IOB_UT
{
    /// <summary>
    /// Create a new INI file to store or load data
    /// </summary>
    public class IniFile
    {
        #region Public Fields

        public string FileName;

        #endregion Public Fields

        // INI filename

        // import windows dll functions

        #region Public Constructors

        /// <summary>
        /// Constructor
        /// </summary>
        /// <PARAM name="INIPath"></PARAM>
        public IniFile(string INIPath)
        {
            FileName = INIPath;
        }

        #endregion Public Constructors

        #region Private Methods

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileInt(string section, string key, int def, string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileSection(string section, IntPtr retVal, uint size, string filePath);

        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        [DllImport("kernel32")]
        private static extern bool WritePrivateProfileSection(string section, string value, string filePath);

        [DllImport("kernel32", CharSet = CharSet.Auto, BestFitMapping = false)]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);

        #endregion Private Methods

        #region Public Methods

        /// <summary>
        /// Delete a key from section
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        public void IniDeleteKey(string Section, string Key)
        {
            WritePrivateProfileString(Section, Key, null, FileName);
        }

        /// <summary>
        /// Completely remove one section
        /// </summary>
        /// <param name="Section"></param>
        public void IniDeleteSection(string Section)
        {
            WritePrivateProfileSection(Section, null, FileName);
        }

        /// <summary>
        /// Return true if section exists
        /// </summary>
        /// <param name="Section"></param>
        /// <returns></returns>
        public bool IniSectionExists(string Section)
        {
            int bytesReturned = 0;
            const int bufferSize = 2048; // max is 32767
            IntPtr pReturnedString = Marshal.AllocCoTaskMem(bufferSize);
            try
            {
                bytesReturned = GetPrivateProfileSection(Section, pReturnedString, bufferSize, FileName);
            }
            finally
            {
                Marshal.FreeCoTaskMem(pReturnedString);
            }
            return (bytesReturned > 0);
        }

        /// <summary>
        /// Read a boolean
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public bool ReadBoolean(string Section, string Key)
        {
            return (ReadInteger(Section, Key, 0) != 0);
        }

        /// <summary>
        /// Read a boolean with default value
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <param name="DefaultVal"></param>
        /// <returns></returns>
        public bool ReadBoolean(string Section, string Key, bool DefaultVal)
        {
            int v = DefaultVal ? 1 : 0;
            return (ReadInteger(Section, Key, v) != 0);
        }

        /// <summary>
        /// Read an integer
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public int ReadInteger(string Section, string Key)
        {
            return GetPrivateProfileInt(Section, Key, 0, FileName);
            //System.Convert.ToInt32(IniReadValue(Section, Key));
        }

        /// <summary>
        /// Read an integer. If not found use default value
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <param name="DefaultVal"></param>
        /// <returns></returns>
        public int ReadInteger(string Section, string Key, int DefaultVal)
        {
            //int temp = System.Convert.ToInt32(IniReadString(Section, Key, Convert.ToString(DefaultVal)));
            //return temp;
            return GetPrivateProfileInt(Section, Key, DefaultVal, FileName);
        }

        /// <summary>
        /// Read a complete section (keys=values)
        /// </summary>
        /// <param name="Section"></param>
        /// Section name
        /// <returns>restituisce delle stringhe keys=values da suddividere appunto come key/val successivamente</returns>
        public string[] ReadSection(string Section)
        {
            const int bufferSize = 2048; // max is 32767

            StringBuilder returnedString = new StringBuilder();

            IntPtr pReturnedString = Marshal.AllocCoTaskMem(bufferSize);
            try
            {
                int bytesReturned = GetPrivateProfileSection(Section, pReturnedString, bufferSize, FileName);
                if (bytesReturned > 0)
                {
                    //bytesReturned -1 to remove trailing \0
                    for (int i = 0; i < bytesReturned - 1; i++)
                    {
                        var currPointer = IntPtr.Add(pReturnedString, i);
                        var currChar = (char)Marshal.ReadByte(currPointer);
                        returnedString.Append(currChar);
                    }
                }
            }
            finally
            {
                Marshal.FreeCoTaskMem(pReturnedString);
            }

            string sectionData = returnedString.ToString();
            return sectionData.Split('\0');
        }

        /// <summary>
        /// Read data from the Ini file
        /// </summary>
        /// <PARAM name="Section"></PARAM>
        /// <PARAM name="Key"></PARAM>
        /// <PARAM name="Path"></PARAM>
        /// <returns></returns>
        public string ReadString(string Section, string Key)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(Section, Key, "", temp, 255, FileName);
            return temp.ToString();
        }

        /// <summary>
        /// Read a string. If not found use default value
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <param name="DefaultVal"></param>
        /// <returns></returns>
        public string ReadString(string Section, string Key, string DefaultVal)
        {
            string temp = ReadString(Section, Key);
            if (temp == "") temp = DefaultVal;
            return temp;
        }

        /// <summary>
        /// Return true if value exists
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public bool ValueExists(string Section, string Key)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(Section, Key, "", temp, 255, FileName);
            return (i > 0);
        }

        /// <summary>
        /// Write a boolean value
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <param name="Value"></param>
        public void WriteBoolean(string Section, string Key, bool Value)
        {
            int flag = Value ? 1 : 0;
            WriteString(Section, Key, Convert.ToString(flag));
        }

        /// <summary>
        /// Write a double value
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <param name="Value"></param>
        public void WriteDouble(string Section, string Key, double Value)
        {
            WriteString(Section, Key, Convert.ToString(Value, NumberFormatInfo.InvariantInfo));
        }

        /// <summary>
        /// Write an integer value
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <param name="Value"></param>
        public void WriteInteger(string Section, string Key, int Value)
        {
            WriteString(Section, Key, Convert.ToString(Value));
        }

        /// <summary>
        /// Write data to the INI file
        /// </summary>
        /// <PARAM name="Section"></PARAM>
        /// Section name
        /// <PARAM name="Key"></PARAM>
        /// Key Name
        /// <PARAM name="Value"></PARAM>
        /// Value Name
        public void WriteString(string Section, string Key, string Value)
        {
            WritePrivateProfileString(Section, Key, Value, FileName);
        }

        #endregion Public Methods
    }
}