local Timer = require("level.timer")
local color = require("core.color")
local Random = function(a, b)
  local min = a
  local max = b
  if b == nil then
    min = 0
    max = a
  end
  return math.random() * (max - min) + min
end
local player, luaTable, spawnRate
local enabled = true
function OnScriptLoaded(level, obj)
  game.SubObject.SetForgetOnCheckpoint(obj)
  player = game.Player.FindPlayer()
  luaTable = {
    minRange = obj:GetLuaTableAttribute("MinRange"),
    maxRange = obj:GetLuaTableAttribute("MaxRange"),
    spawnRate = obj:GetLuaTableAttribute("SpawnRate"),
    spawnMove = obj:GetLuaTableAttribute("SpawnMove"),
    spawnDepth = obj:GetLuaTableAttribute("SpawnDepth"),
    static = true,
    fadeStart = 150,
    fadeEnd = 200
  }
end
function OnStart(level, obj)
  StartSpawnTimer(math.random() * luaTable.spawnRate, level, obj)
  spawnRate = luaTable.spawnRate
  game.SubObject.Sleep(obj)
end
function StartSpawnTimer(time, level, obj)
  Timer.StartLevelTimer(time, TimerCallback, level, obj)
end
function TimerCallback(timer, level, obj)
  if not enabled then
    ResetTimer(level, obj, true)
    return
  end
  FindWater(level, obj)
end
function ResetTimer(level, obj, success)
  if success then
    spawnRate = luaTable.spawnRate
  else
    spawnRate = math.max(spawnRate * 0.5, 0.5)
  end
  StartSpawnTimer(spawnRate, level, obj)
end
function FindBoat(level)
  local closestBoat = game.Boat.GetPlayerBoat()
  local closestDistance
  if closestBoat then
    return closestBoat
  end
  local playerPosition = player.WorldPosition
  for _, boat in ipairs(level:FindGameObjects("Boat00")) do
    local distance = boat.WorldPosition:Distance(playerPosition)
    if not closestBoat or closestDistance > distance then
      closestBoat = boat
      closestDistance = distance
    end
  end
  return closestBoat
end
local up = engine.Vector.New(0, 1, 0)
local lineFilter = {
  EntityType = game.CollisionType.New("kWater"),
  CollidesWith = -1
}
local sphereFilter = {
  EntityType = game.CollisionType.New("kEnvironment", "kInvisibleBarrier", "kPhantom"),
  CollidesWith = -1,
  FindAnything = true
}
local waterPosition
function FindWater(level, obj)
  local boat = FindBoat(level)
  if not boat then
    ResetTimer(level, obj, false)
    return
  end
  local playerPosition = player.WorldPosition
  local boatPosition = boat.WorldPosition
  local cameraForward = game.Camera:GetOrbitForward()
  local cameraForwardXZ = engine.Vector.New(cameraForward.x, 0, cameraForward.z):Normalized()
  local cameraFoV = game.Camera:GetOutputFoV()
  local center = engine.Vector.New(playerPosition.x, boatPosition.y, playerPosition.z)
  local playerBoat = game.Boat.GetPlayerBoat()
  if playerBoat then
    local boatVelocity = playerBoat:GetVelocity()
    local boatSpeed = boatVelocity:Length()
    center = center + cameraForwardXZ * boatSpeed + boatVelocity
  end
  local angle = cameraFoV * 0.5
  local randomRange = Random(luaTable.minRange, luaTable.maxRange)
  local randomAngle = Random(-angle, angle)
  local randomPosition = center + randomRange * cameraForwardXZ:RotateXZ(randomAngle)
  local lineStart = randomPosition + up * 0.5
  local lineEnd = randomPosition - up * 1.5
  if game.World.DeferredRaycastCollision then
    game.World.DeferredRaycastCollision(obj, "FindOpenSpace", lineStart, lineEnd, lineFilter)
  else
    local lineHit = game.World.RaycastCollision(lineStart, lineEnd, lineFilter)
    FindOpenSpace(level, obj, lineHit)
  end
end
function FindOpenSpace(level, obj, lineHit)
  if not lineHit then
    ResetTimer(level, obj, false)
    return
  end
  sphereFilter.ExcludeGameObject = lineHit.GameObject
  waterPosition = lineHit.Position
  local radius = 5
  if game.World.DeferredSphereCollision then
    game.World.DeferredSphereCollision(obj, "Spawn", waterPosition, radius, sphereFilter)
  else
    local sphereHit = game.World.SphereCollision(waterPosition, radius, sphereFilter)
    Spawn(level, obj, sphereHit)
  end
end
function Spawn(level, obj, sphereHit)
  if sphereHit then
    ResetTimer(level, obj, false)
    return
  end
  obj:SpawnWildlife({
    FleeDistance = 0,
    RespawnTime = 0,
    Speed = 0,
    Acceleration = 0,
    BankLimit = 0,
    StartIdle = false,
    RandomStartPos = false,
    Character = GetCharacterName(),
    Curve = "",
    SpawnMove = luaTable.spawnMove,
    Type = 0,
    Position = waterPosition - up * luaTable.spawnDepth,
    Facing = GetSpawnFacing()
  })
  ResetTimer(level, obj, true)
end
function GetSpawnFacing()
  return engine.Vector.New(0, 0, -1):RotateXZ(Random(360))
end
function GetCharacterName()
  if math.random(4) > 1 then
    return "Fish10"
  end
  return "Fish00"
end
function Enable()
  enabled = true
end
function Disable()
  enabled = false
end
