objectdef ActorToMonitor
{
    variable string ID
    variable string Name
    variable int Health
    variable string TargetName
    variable int ThreatToNext
    variable float Distance

    method Initialize(string id, string name, int health, string targetName, int threatToNext, float distance)
    {
        ID:Set["${id}"]
        Name:Set["${name}"]
        Health:Set[${health}]
        TargetName:Set["${targetName}"]
        ThreatToNext:Set[${threatToNext}]
        Distance:Set[${distance}]
    }

    method FromJSON(jsonvalueref jo)
    {
        ID:Set["${jo.Get[ID]~}"]
        Name:Set["${jo.Get[Name]~}"]
        Health:Set["${jo.Get[Health]~}"]
        TargetName:Set["${jo.Get[Health]~}"]
        ThreatToNext:Set["${jo.Get[ThreatToNext]~}"]
        Distance:Set["${jo.Get[Distance]~}"]
    }

    member:jsonvalueref AsJSON()
    {
        variable jsonvalue jo="{}"
        jo:SetString[ID, "${ID~}"]
        jo:SetString[Name, "${Name~}"]
        jo:SetString[Health, "${Health~}"]
        jo:SetString[TargetName, "${TargetName~}"]
        jo:SetString[ThreatToNext, "${ThreatToNext~}"]
        jo:SetString[Distance, "${Distance}"]

        return jo
    }
}

objectdef OSAController
{
    variable string SelectedItem
    variable collection:ActorToMonitor ActorsWithTarget
    variable string locationStorageFile = "${LavishScript.HomeDirectory}/Scripts/mr/saves/osa/location.json"
    variable string windowName = "mr.osa.window"

	method Initialize()
	{
        variable jsonvalue location
        location:ParseFile["${locationStorageFile}"]
        LGUI2:LoadPackageFile[osa.json]
        LGUI2.Element["${windowName}"]:ApplyStyleJSON["${location.AsJSON~}"]
	}

	method Shutdown()
	{
        variable jsonvalue location = ${LGUI2.Element["${windowName}"].StorePlacement[1]}
        location:WriteFile["${locationStorageFile}"]
		LGUI2:UnloadPackageFile[osa.json]
	}

    method OnClose()
    {
        Script:End
    }

    method OnChangeTarget()
    {
        Actor[${SelectedItem}]:DoTarget
        Context:SetHandled[1]
    }

    method RefreshMobs()
    {
        variable index:actor Actors
        variable iterator ActorIterator
        variable set CurrentActors
        variable bool FireRefreshEvent=FALSE
        
        EQ2:QueryActors[Actors,  Type =- "NPC" && Target != NULL]
        Actors:GetIterator[ActorIterator]

        if ${ActorIterator:First(exists)}
        {
            do
            {
                if ${ActorIterator.Value.Target.Name.NotNULLOrEmpty}
                {
                    ; TODO: Maybe implement group/raid only checkbox instead of that being the default?
                    if ${Me.Name.Equal[${ActorIterator.Value.Target.Name}]} || ${Me.Group[${ActorIterator.Value.Target.Name}](exists)} || ${Me.Raid[${ActorIterator.Value.Target.Name}](exists)}
                    {
                        if !${ActorsWithTarget.Element[${ActorIterator.Value.ID}](exists)}
                        {
                            ActorsWithTarget:Set["${ActorIterator.Value.ID}", "${ActorIterator.Value.ID}", "${ActorIterator.Value.Name}", ${ActorIterator.Value.Health}, "${ActorIterator.Value.Target.Name}", ${ActorIterator.Value.ThreatToNext}, ${ActorIterator.Value.Distance}]
                            
                        }
                        else
                        {
                            ActorsWithTarget.Element["${ActorIterator.Value.ID}"].TargetName:Set["${ActorIterator.Value.Target.Name}"]
                            ActorsWithTarget.Element["${ActorIterator.Value.ID}"].Health:Set["${ActorIterator.Value.Health}"]
                            ActorsWithTarget.Element["${ActorIterator.Value.ID}"].ThreatToNext:Set["${ActorIterator.Value.ThreatToNext}"]
                            ActorsWithTarget.Element["${ActorIterator.Value.ID}"].Distance:Set["${ActorIterator.Value.Distance}"]
                        }

                        FireRefreshEvent:Set[TRUE]
                        CurrentActors:Add["${ActorIterator.Value.ID}"]
                    }
                }
            }
            while ${ActorIterator:Next(exists)}
        }

        if ${ActorsWithTarget.FirstKey(exists)}
        {
            do
            {
                if !${CurrentActors.Contains[${ActorsWithTarget.CurrentKey}]}
                {
                    ActorsWithTarget:Erase[${ActorsWithTarget.CurrentKey}]

                    FireRefreshEvent:Set[TRUE]
                }
            }
            while ${ActorsWithTarget.NextKey(exists)}
        }

        if ${FireRefreshEvent}
        {
            LGUI2.Element[MrOSAController.events]:FireEventHandler[onUpdateActors]
        }
    }
}

variable(global) OSAController MrOSAController

function main()
{
    while 1
    {
        MrOSAController:RefreshMobs
        wait 5
    }
}
