Imports System.Collections.Generic
Imports System.Text.RegularExpressions

Public Class JobConfigParser
    Private Shared JobOptionsRegex As New Regex("(?<enabled>True|False|Debug)\|(?<cron>[\w\d\s,\?*-/]*)(?:\|(?<args>(?:\w*::[^,\n]+,?)*))?")
    Private Shared JobArgumentsRegex As New Regex("(?:(?:\w+::[^,\n]+,?)?)+")
    Private Const ARGS_ITEM_DELIMITER As String = ","
    Private Const ARGS_KEYVALUE_DELIMITER As String = "::"
    Private Const ARGS_LIST_DELIMITER As String = "|"

    ''' <summary>
    ''' Parse a job config string. ex: True|0 0/3 * * * ?|Arg1::Foo,Arg2::Bar
    ''' </summary>
    ''' <param name="ConfigString"></param>
    ''' <returns>A populated JobConfig object</returns>
    Public Shared Function ParseConfig(ConfigString As String) As JobConfig
        If JobOptionsRegex.IsMatch(ConfigString) Then
            Dim oMatches = JobOptionsRegex.Matches(ConfigString)
            Dim oOptions As New JobConfig

            Dim oSplitOptions As String() = ConfigString.Split(ARGS_LIST_DELIMITER)

            If oSplitOptions.Length = 3 Then
                oOptions = ParseEnabled(oSplitOptions(0), oOptions)
                oOptions.CronExpression = oSplitOptions(1)
                oOptions.Arguments = ParseOptionalArguments(oSplitOptions(2))
            ElseIf oSplitOptions.Length = 2 Then
                oOptions = ParseEnabled(oSplitOptions(0), oOptions)
                oOptions.CronExpression = oSplitOptions(1)
                oOptions.Arguments = New Dictionary(Of String, String)
            Else
                Throw New ArgumentException("Config Malformed")
            End If

            Return oOptions
        Else
            Throw New ArgumentException("Config Malformed")
        End If
    End Function

    Public Shared Function ParseEnabled(EnabledValue As String, Options As JobConfig) As JobConfig
        Select Case EnabledValue
            Case "True"
                Options.Enabled = True
                Options.StartImmediately = False
            Case "Debug"
                Options.Enabled = True
                Options.StartImmediately = True
            Case Else
                Options.Enabled = False
                Options.StartImmediately = False
        End Select

        Return Options
    End Function

    Private Shared Function ParseOptionalArguments(ArgsString As String) As Dictionary(Of String, String)
        Dim oArgsDictionary As New Dictionary(Of String, String)

        If JobArgumentsRegex.IsMatch(ArgsString) Then
            Dim oArgs As String() = ArgsString.Split(ARGS_ITEM_DELIMITER)

            For Each oArg In oArgs
                Dim oDelimiter As String() = New String() {ARGS_KEYVALUE_DELIMITER}
                Dim oArgSplit = oArg.Split(oDelimiter, StringSplitOptions.RemoveEmptyEntries)
                Regex.Split(oArg, "::")

                If oArgSplit.Length = 2 Then
                    oArgsDictionary.Add(oArgSplit(0), oArgSplit(1))
                Else
                    Throw New ArgumentException("Config Malformed")
                End If
            Next
        End If

        Return oArgsDictionary
    End Function
End Class
