objectdef BotController
{
    variable bool IsBotRunning = FALSE
    variable bool IsShowingSettings = FALSE
    variable jsonvalue savedSettings = "{}"
    variable jsonvalue currentProfile = "{}"
    variable jsoniterator castStackIterator
    variable jsonvalue abilities = "{}"

    method Initialize()
	{
		LGUI2:LoadPackageFile["bot.json"]
        
        savedSettings:ParseFile["${LavishScript.HomeDirectory}/scripts/mr/bot/profiles/${Me.Name}_${Me.SubClass}.json"]
	    if ${savedSettings.Type.NotEqual["object"]}
        {
            echo "Error parsing saved settings"
            return
        }

        abilities:ParseFile["${LavishScript.HomeDirectory}/scripts/mr/bot/ability_exports/${Me.Name}_${Me.SubClass}.json"]
        if ${jo.Type.NotEqual["object"]}
        {
            echo "Error parsing ability list"
            return
        }

        currentProfile:SetValue["${savedSettings.Get[${savedSettings.Get["default"]}]}"]
        currentProfile.Get["castStack"]:GetIterator[castStackIterator]
    }

	method Shutdown()
	{
		LGUI2:UnloadPackageFile["bot.json"]
	}
   
    member:string StartButtonText()
    {
        if ${IsBotRunning}
        {
            return "Stop"
        }
        else
        {
            return "Start"
        }
    }

    member:string SettingsButtonText()
    {
        if ${IsShowingSettings}
        {
            return "Hide Settings"
        }
        else
        {
            return "Show Settings"
        }
    }

    method OnClose()
    {
        Script:End
    }

    method OnCloseSettings()
    {
        IsShowingSettings:Set[FALSE]
        LGUI2.Element[mr.bot.settings]:SetVisibility[Hidden]
    }

    method ToggleBot()
    {
        IsBotRunning:Set[${IsBotRunning.Not}]
    }

    method ToggleSettings()
    {
        if ${IsShowingSettings}
        {
            LGUI2.Element[mr.bot.settings]:SetVisibility[Hidden]
        }
        else
        {
          LGUI2.Element["mr.bot.settings"]:SetVisibility[Visible]
        }

        IsShowingSettings:Set[${IsShowingSettings.Not}]
    }

    member:jsonvalueref GetHighestVersionOfAbility(string abilityName)
    {
        if !${abilityName(exists)}
        {
            echo "ability name not set"
            return
        }

        variable jsonvalueref highestVersion = "{}"
        variable jsoniterator abilityIterator
        abilities.Get["${abilityName}"]:GetIterator[abilityIterator]

        if ${abilityIterator:First(exists)}
        {
            do
            {
                if !${highestVersion.Get["level"]}
                {
                    highestVersion:SetReference[abilityIterator.Value]
                }
                elseif  ${highestVersion.Get["level"]} < ${abilityIterator.Value.Get["level"]}
                {
                    highestVersion:SetReference[abilityIterator.Value]
                }
            }
            while ${abilityIterator:Next(exists)}
        }

        return highestVersion
    }

    member:string GetBuiltinAlias(string aliasName)
    {
        if ${aliasName.Equal["@Me"]}
        {
            return Me.Name
        }
    }

    member:string GetActualTarget(string givenTarget)
    {
        if ${givenTarget.Left[1].Equal["*"]}
        {
            ; look up alias
        }
        elseif ${givenTarget.Left[1].Equal["@"]}
        {
            ; built up alias
            return This.GetBuiltinAlias[${givenTarget}]
        }
        elseif ${givenTarget.Left[4].Equal["Pet:"]}
        {
            ; pet
        }
        else
        {
            return givenTarget
        }
    }

    method Pulse()
    {
        if ${IsBotRunning.Not}
        {
            return
        }

        variable int64 currentAbilityId
        variable string abilityTarget

        if ${Me.CastingSpell}
        {
            return
        }
        if ${castStackIterator:First(exists)}
        {
            do
            {
                if ${castStackIterator.Value.Get["action"].Equal["ability"]} && ${castStackIterator.Value.Get["type"].Equal["Buff"]}
                {
                    currentAbilityId:Set[${This.GetHighestVersionOfAbility[${castStackIterator.Key}].Get["id"]}]

                    if ${currentAbilityId} > 0
                    {
                        if ${Me.Ability[id, ${currentAbilityId}].IsReady}
                        {
                            abilityTarget:Set[]
                            echo "Target ${castStackIterator.Value.Get["target"]}"
                            echo "Casting ${castStackIterator.Key}"
                            Me.Ability[id, ${currentAbilityId}]:Use
                            return
                        }
                    }
                }
                
            }
            while ${castStackIterator:Next(exists)}
        }
    }
}

#include "settings_controller.iss"

variable(global) BotController MRBotController
variable(global) SettingsController MRSettingsController

function main() 
{
    while 1
    {
        MRBotController:Pulse
        wait 5
    }
}