local timer = require("level.timer")
local DL = require("design.DesignerLibrary")
local line
local frontPoints = {}
local points = {}
local thisLevel, origin
local enemyList = {}
local enemySize = 0
local enemyIndex = 1
local enemyGO
local maxChainCount = 4
local segmentMax = 6
local segmentCount = 0
local INIT = 1
local TARGET = 2
local HOME = 3
local EXPLODE = 4
local END = 5
local state = INIT
local initialPoint
local speed = 30
local currentDist = 0
local percentageGain = 0.1
local currentPercentage = 0
local deleteIndex = 0
local shockConcussion = "CNC_SHOCK_CHAIN_EXPLOSION"
function OnScriptLoaded(level, go)
  thisLevel = level
  if game.Wallets.HasResource("HERO", "SonPerk_ShockArrow_DetonationConduit") then
    shockConcussion = "CNC_SHOCK_CHAIN_EXPLOSION_STATUS"
  end
  if game.Wallets.HasResource("HERO", "SonPerk_ShockArrow_OnHitSpark") then
    maxChainCount = maxChainCount + 2
  end
  local allenemies = game.Player.FindPlayer():FindEnemies(50)
  local distance = 5
  local thisPos = go.WorldPosition
  if origin == nil then
    for _, i in ipairs(allenemies) do
      local thisDistance = (i.WorldPosition - thisPos):Length()
      if distance > thisDistance then
        origin = i
        distance = thisDistance
      end
    end
  end
  if origin ~= nil then
    allenemies = FindLivingFriendlies(origin, 20, true)
    AddToEnemyList(allenemies)
  end
end
function AddToEnemyList(thisList)
  local newList = thisList
  table.insert(newList, origin)
  local sizeOfList = #newList
  local addedEnemy = 0
  if sizeOfList == 1 then
    return
  end
  while addedEnemy < maxChainCount do
    table.insert(enemyList, thisList[addedEnemy % sizeOfList + 1])
    addedEnemy = addedEnemy + 1
  end
  enemySize = #enemyList
  return
end
function SetOriginator(go, myself)
  origin = myself
end
function OnUpdate(level, go)
  if enemySize <= 1 then
    if line ~= nil then
      line:Destroy()
    end
    for _, i in ipairs(frontPoints) do
      if i ~= nil then
        i:Destroy()
      end
    end
    go:Destroy()
    return
  end
  if state == INIT then
    if EndIt() then
      return
    end
    SoundSpawnLightning()
    SetPosition(GetJointPosition(origin, "JOPelvis1"))
    state = TARGET
  elseif state == TARGET then
    if EndIt() then
      return
    end
    enemyGO = nil
    while enemyIndex < enemySize do
      enemyGO = enemyList[enemyIndex]
      if enemyGO == nil or enemyGO ~= nil and (enemyGO:GetCreature() == nil or enemyGO:IsDead() == true) then
        enemyIndex = enemyIndex + 1
      else
        initialPoint = points[1]
        local pelvisLocation = GetJointPosition(enemyGO, "JOPelvis1")
        if pelvisLocation ~= nil and initialPoint ~= nil then
          local dist = (initialPoint - pelvisLocation):Length()
          local time = dist / speed
          if time <= 0 then
            time = 0.01
          end
          percentageGain = 1 / time
          currentPercentage = 0
          state = HOME
          enemyIndex = enemyIndex + 1
          break
        else
          if initialPoint == nil then
            state = END
            return
          end
          enemyIndex = enemyIndex + 1
        end
      end
    end
    if enemyGO == nil then
      state = END
    end
  elseif state == HOME then
    if EndIt() then
      return
    end
    if enemyGO == nil then
      state = TARGET
      return
    end
    currentPercentage = currentPercentage + percentageGain * level:GetUnitTime()
    if 1 < currentPercentage then
      currentPercentage = 1
      state = EXPLODE
    end
    local newPoint = initialPoint + (GetJointPosition(enemyGO, "JOPelvis1") - initialPoint) * currentPercentage
    SetPosition(newPoint)
  elseif state == EXPLODE then
    if EndIt() then
      return
    end
    local concussionParams = {}
    concussionParams.WorldLocation = GetJointPosition(enemyGO, "JOPelvis1")
    concussionParams.Creature = game.AI.FindSon()
    concussionParams.EnemyId = DL.HashCreatureID(game.Player.FindPlayer(), "SON00")
    concussionParams.Tweak = shockConcussion
    game.Combat.PlayConcussion(concussionParams)
    state = TARGET
    points[1] = GetJointPosition(enemyGO, "JOPelvis1")
  elseif state == END then
    local pointSize = #points
    if pointSize > deleteIndex + 1 and points[1] ~= nil then
      SetPosition(points[1] + engine.Vector.New(0, math.random() * 0.2, 0))
      deleteIndex = deleteIndex + 1
    else
      enemySize = 0
    end
  end
end
function EndIt()
  local endIt = enemyIndex > maxChainCount
  if endIt then
    state = END
  end
  return endIt
end
function SetPosition(newPoint)
  if line == nil then
    line = game.FX.Spawn("ElectricShock_WeaponTrail", thisLevel, {Scale = 1.5})
    table.insert(points, 1, newPoint)
  end
  line:SetWorldPosition(newPoint)
end
function GetJointPosition(thisGO, jointname)
  if thisGO == nil then
    return nil
  end
  local jointindex = thisGO:FindJointIndex(jointname)
  if jointindex ~= nil then
    return thisGO:GetWorldJointPosition(jointindex)
  end
  return thisGO.WorldPosition
end
function FindLivingFriendlies(ai, radius, sort_closest)
  local enemies = ai:FindFriendlies(radius)
  for i = #enemies, 1, -1 do
    if enemies[i]:GetCreature():GetHitPoints() <= 0 or ai == enemies[i] then
      table.remove(enemies, i)
    end
  end
  return enemies
end
function SoundSpawnLightning()
end
