local LD = require("design.LevelDesignLibrary")
local thisObj, player, son, freya, luaTable, enabled, leadTheWayParams
local curves = {}
local checkpoint
local GetDefaultLeadTheWayParams = function()
  local defaultParams = {
    Role = "leader",
    TargetCreature = nil,
    Speed = luaTable.speed,
    LeaderDistance_Wait = luaTable.leaderDistance_Wait,
    LeaderDistance_Continue = luaTable.leaderDistance_Continue,
    LeaderDistance_Backtrack = luaTable.leaderDistance_Backtrack,
    LeaderDistance_BacktrackDone = luaTable.LeaderDistance_BacktrackDone,
    FollowerDistance_CaughtUp = luaTable.followerDistance_CaughtUp,
    FollowerDistance_Continue = luaTable.followerDistance_Continue,
    TargetCreatureDirBufferRad = luaTable.directionChangeBufferRadius,
    AvoidDistance_Start = luaTable.avoidDistance_Start,
    AvoidDistance_Wait = luaTable.avoidDistance_Wait,
    RangeTest_Max = luaTable.rangeTest_Max,
    RangeTest_MaxY = luaTable.rangeTest_MaxY,
    RangeTest_AllowSwitch = luaTable.rangeTest_AllowSwitch,
    AvailableInCombat = luaTable.availableInCombat,
    AvailableOutOfCombat = luaTable.availableOutOfCombat,
    Loop = luaTable.loop
  }
  if luaTable.additionalBehavior == "Stay Near Player" then
    defaultParams.Role = "relaxedFollower"
  elseif luaTable.additionalBehavior == "Stay Behind Freya" then
    defaultParams.Role = "follower"
    assert(luaTable.character ~= "Freya00", "Lead The Way module configured incorrectly. Freya is set to use the spline, and also set to follow Freya. Fix 'Additional Behavior' in the Lua Toolbox for module. " .. LD.GetParentTrace(thisObj))
  elseif luaTable.additionalBehavior == "Avoid Enemies" then
    defaultParams.Role = "avoid"
  elseif luaTable.additionalBehavior == "Wait for Player reverse" then
    defaultParams.Role = "leader_reverse"
  end
  return defaultParams
end
function OnScriptLoaded(level, obj)
  thisObj = obj
  player = game.Player.FindPlayer()
  luaTable = {
    character = obj:GetLuaTableAttribute("Character"),
    splineObject = LD.ConvertStringListToTable(obj:GetLuaTableAttribute("SplineObject")),
    speed = obj:GetLuaTableAttribute("Speed"),
    additionalBehavior = obj:GetLuaTableAttribute("AdditionalBehavior"),
    leaderDistance_Wait = obj:GetLuaTableAttribute("LeaderDistance_Wait"),
    leaderDistance_Continue = obj:GetLuaTableAttribute("LeaderDistance_Continue"),
    leaderDistance_Backtrack = obj:GetLuaTableAttribute("LeaderDistance_Backtrack"),
    LeaderDistance_BacktrackDone = obj:GetLuaTableAttribute("LeaderDistance_BacktrackDone"),
    followerDistance_CaughtUp = obj:GetLuaTableAttribute("FollowerDistance_CaughtUp"),
    followerDistance_Continue = obj:GetLuaTableAttribute("FollowerDistance_Continue"),
    directionChangeBufferRadius = obj:GetLuaTableAttribute("DirectionChangeBufferRadius"),
    startEnabled = obj:GetLuaTableAttribute("StartEnabled"),
    rangeTest = obj:GetLuaTableAttribute("RangeTest"),
    availableInCombat = obj:GetLuaTableAttribute("AvailableInCombat"),
    availableOutOfCombat = obj:GetLuaTableAttribute("AvailableOutOfCombat"),
    avoidDistance_Start = obj:GetLuaTableAttribute("AvoidDistance_Start"),
    avoidDistance_Wait = obj:GetLuaTableAttribute("AvoidDistance_Wait"),
    rangeTest_Max = obj:GetLuaTableAttribute("RangeTest_Max"),
    rangeTest_MaxY = obj:GetLuaTableAttribute("RangeTest_MaxY"),
    rangeTest_AllowSwitch = obj:GetLuaTableAttribute("RangeTest_AllowSwitch"),
    loop = obj:GetLuaTableAttribute("Loop")
  }
  leadTheWayParams = GetDefaultLeadTheWayParams()
end
function OnStart(level, obj)
  for _, name in ipairs(luaTable.splineObject) do
    local curve = level:FindSingleNavCurve(name)
    if curve then
      table.insert(curves, curve)
    end
  end
  if checkpoint then
    enabled = checkpoint.enabled
    checkpoint = nil
    return
  end
  if luaTable.startEnabled then
    Enable()
  end
end
function OnUpdate(level, obj)
  if player:IsInVehicle() == true then
    return
  end
  local combatStatus = game.Combat.GetCombatStatus()
  if not luaTable.availableInCombat and combatStatus then
    return
  elseif not luaTable.availableOutOfCombat and not combatStatus then
    return
  end
  if not enabled then
    game.SubObject.Sleep(obj)
    return
  end
  local character = GetCharacter()
  if not character then
    return
  end
  if not character:IsAvailableInLevel() then
    return
  end
  character:CallScript("SubmitNavCurve", {
    curves = curves,
    rangeTest = luaTable.rangeTest ~= "Off",
    params = GetLeadTheWayParams()
  })
end
function OnSaveCheckpoint(level, obj)
  return {enabled = enabled}
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  checkpoint = savedInfo
end
function Enable()
  enabled = true
  game.SubObject.Wake(thisObj)
end
function Disable()
  enabled = false
  game.SubObject.Sleep(thisObj)
end
function GetCharacter()
  if luaTable.character == "Son" then
    if son == nil then
      son = game.AI.FindSon()
    end
    return son
  end
  local go = game.World.FindGameObjectsByMarker(luaTable.character)[1]
  return go and go:GetCreature():GetAI()
end
function GetLeadTheWayParams()
  if leadTheWayParams.TargetCreature ~= nil then
    return leadTheWayParams
  end
  if luaTable.additionalBehavior == "Stay Behind Freya" then
    if freya == nil then
      local ND = require("design.NarrativeDesignLibrary")
      freya = ND.FindFreya()
    end
    leadTheWayParams.TargetCreature = freya
  else
    leadTheWayParams.TargetCreature = player
  end
  return leadTheWayParams
end
function UpdateLeadTheWayParams(p)
  assert(p.Role == nil and p.TargetCreature == nil, "Invalid parameter.")
  if p.Speed then
    leadTheWayParams.Speed = p.Speed
  end
  if p.LeaderDistance_Wait then
    leadTheWayParams.LeaderDistance_Wait = p.LeaderDistance_Wait
  end
  if p.LeaderDistance_Continue then
    leadTheWayParams.LeaderDistance_Continue = p.LeaderDistance_Continue
  end
  if p.LeaderDistance_Backtrack then
    leadTheWayParams.LeaderDistance_Backtrack = p.LeaderDistance_Backtrack
  end
  if p.LeaderDistance_BacktrackDone then
    leadTheWayParams.LeaderDistance_BacktrackDone = p.LeaderDistance_BacktrackDone
  end
  if p.FollowerDistance_CaughtUp then
    leadTheWayParams.FollowerDistance_CaughtUp = p.FollowerDistance_CaughtUp
  end
  if p.FollowerDistance_Continue then
    leadTheWayParams.FollowerDistance_Continue = p.FollowerDistance_Continue
  end
  if p.TargetCreatureDirBufferRad then
    leadTheWayParams.TargetCreatureDirBufferRad = p.TargetCreatureDirBufferRad
  end
  if p.AvoidDistance_Start then
    leadTheWayParams.AvoidDistance_Start = p.AvoidDistance_Start
  end
  if p.AvoidDistance_Wait then
    leadTheWayParams.AvoidDistance_Wait = p.AvoidDistance_Wait
  end
  if p.RangeTest_Max then
    leadTheWayParams.RangeTest_Max = p.RangeTest_Max
  end
  if p.RangeTest_MaxY then
    leadTheWayParams.RangeTest_MaxY = p.RangeTest_MaxY
  end
  if p.RangeTest_AllowSwitch then
    leadTheWayParams.RangeTest_AllowSwitch = p.RangeTest_AllowSwitch
  end
  if p.Loop then
    leadTheWayParams.Loop = p.Loop
  end
end
function ResetLeadTheWayParams()
  leadTheWayParams = GetDefaultLeadTheWayParams()
end
