Imports System.IO
Imports System.Collections
'*************************************************************************************
'* Adapted from http://bytes.com/topic/net/insights/797169-reading-parsing-ini-file-c
'*************************************************************************************
Public Class IniParser
    Private keyPairs As New Hashtable()
    Private iniFilePath As [String]

    Private Structure SectionPair
        Public Section As [String]
        'Public Key As [String]
    End Structure

    ''' <summary>
    ''' Opens the INI file at the given path and enumerates the values in the IniParser.
    ''' </summary>
    ''' <param name="iniPath">Full path to INI file.</param>
    Public Sub New(iniPath As [String])
        Dim iniFile As TextReader = Nothing
        Dim strLine As [String] = Nothing
        Dim currentRoot As [String] = Nothing
        Dim keyPair As [String]() = Nothing

        iniFilePath = iniPath

        If File.Exists(iniPath) Then
            Try
                iniFile = New StreamReader(iniPath)

                strLine = iniFile.ReadLine()

                While strLine IsNot Nothing
                    strLine = strLine.Trim().ToUpper()

                    If strLine IsNot Nothing AndAlso (String.Compare(strLine, "") <> 0) Then
                        If strLine.StartsWith("[") AndAlso strLine.EndsWith("]") Then
                            currentRoot = strLine.Substring(1, strLine.Length - 2)
                        Else
                            ' keyPair = strLine.Split(New Char() {"="c}, 2)

                            Dim sectionPair As New SectionPair
                            Dim value As String = Nothing

                            If currentRoot Is Nothing Then
                                currentRoot = "ROOT"
                            End If

                            sectionPair.Section = currentRoot
                            'sectionPair.Key = keyPair(0)

                            'If keyPair.Length > 1 Then
                            value = strLine
                            'End If

                            keyPairs.Add(currentRoot, value)
                        End If
                    End If

                    strLine = iniFile.ReadLine()

                End While
            Catch ex As Exception
                Throw ex
            Finally
                If iniFile IsNot Nothing Then
                    iniFile.Close()
                End If
            End Try
        Else
            Throw New FileNotFoundException("Unable to locate " & iniPath)
        End If
    End Sub

    ''' <summary>
    ''' Returns the value for the given section, key pair.
    ''' </summary>
    ''' <param name="sectionName">Section name.</param>
    Public Function GetSetting(sectionName As String) As String
        Dim sectionPair As SectionPair
        sectionPair.Section = sectionName.ToUpper()
        'sectionPair.Key = settingName.ToUpper()

        Return DirectCast(keyPairs(sectionPair.Section), [String])
    End Function

    'Public Function EnumSection(sectionName As [String]) As [String]()
    '    Dim tmpArray As New ArrayList()

    '    For Each pair As SectionPair In keyPairs.Keys
    '        If pair.Section = sectionName.ToUpper() Then
    '            tmpArray.Add(pair.Key)
    '        End If
    '    Next

    '    Return DirectCast(tmpArray.ToArray(GetType([String])), [String]())
    'End Function

    ''' <summary>
    ''' Adds or replaces a setting to the table to be saved.
    ''' </summary>
    ''' <param name="sectionName">Section to add under.</param>
    ''' <param name="settingName">Key name to add.</param>
    ''' <param name="settingValue">Value of key.</param>
    Public Sub AddSetting(sectionName As [String], settingName As [String], settingValue As [String])
        Dim sectionPair As SectionPair
        sectionPair.Section = sectionName.ToUpper()
        'sectionPair.Key = settingName.ToUpper()

        If keyPairs.ContainsKey(sectionPair) Then
            keyPairs.Remove(sectionPair)
        End If

        keyPairs.Add(sectionPair, settingValue)
    End Sub

    ''' <summary>
    ''' Adds or replaces a setting to the table to be saved with a null value.
    ''' </summary>
    ''' <param name="sectionName">Section to add under.</param>
    ''' <param name="settingName">Key name to add.</param>
    Public Sub AddSetting(sectionName As [String], settingName As [String])
        AddSetting(sectionName, settingName, Nothing)
    End Sub

    ''' <summary>
    ''' Remove a setting.
    ''' </summary>
    ''' <param name="sectionName">Section to add under.</param>
    ''' <param name="settingName">Key name to add.</param>
    Public Sub DeleteSetting(sectionName As [String], settingName As [String])
        Dim sectionPair As SectionPair
        sectionPair.Section = sectionName.ToUpper()
        'sectionPair.Key = settingName.ToUpper()

        If keyPairs.ContainsKey(sectionPair) Then
            keyPairs.Remove(sectionPair)
        End If
    End Sub

    ''' <summary>
    ''' Save settings to new file.
    ''' </summary>
    ''' <param name="newFilePath">New file path.</param>
    Public Sub SaveSettings(newFilePath As [String])
        Dim sections As New ArrayList()
        Dim tmpValue As [String] = ""
        Dim strToSave As [String] = ""

        For Each sectionPair As SectionPair In keyPairs.Keys
            If Not sections.Contains(sectionPair.Section) Then
                sections.Add(sectionPair.Section)
            End If
        Next

        For Each section As [String] In sections
            strToSave += ("[" & section & "]" & Convert.ToChar(13) & Convert.ToChar(10))

            For Each sectionPair As SectionPair In keyPairs.Keys
                If sectionPair.Section = section Then
                    tmpValue = DirectCast(keyPairs(sectionPair), [String])

                    If tmpValue IsNot Nothing Then
                        tmpValue = "=" & tmpValue
                    End If

                    strToSave += (tmpValue & Convert.ToChar(13) & Convert.ToChar(10))
                End If
            Next

            strToSave += Convert.ToChar(13) & Convert.ToChar(10)
        Next

        Try
            Dim tw As TextWriter = New StreamWriter(newFilePath)
            tw.Write(strToSave)
            tw.Close()
        Catch ex As Exception
            Throw ex
        End Try
    End Sub

    ''' <summary>
    ''' Save settings back to ini file.
    ''' </summary>
    Public Sub SaveSettings()
        SaveSettings(iniFilePath)
    End Sub
End Class

