local Entity = import('/lua/sim/Entity.lua').Entity
local utilities = import('/lua/utilities.lua')
local EffectTemplate = import('/lua/EffectTemplates.lua')
#local childMarker = BounceMarker(CreateBouncerSpec(TargetRadius, TargetNumber, BounceDamage, FullDamage, BouncerTime, DoStun, AttackBeams))

#Explanation of spec entries:
#spec.
#parent = the unit that fired the initial shot
#AttackBeams = {'/effects/emitters/seraphim_othuy_beam_01_emit.bp'} is the default beam, otherwise, specify here.
#TargetRadius = how far to check for targets to jump to
#TargetNumber = if 0 unlimited, otherwise maximum number of targets to jump to.
#BounceNumber = if 0 unlimited, otherwise, maximum number of jumps to make.
#Damage = starting BounceDamage, it does damage equal to current damage - target health on the next jump to all targets it jumps to
#FullDamage = if 1, it ignores the damage it does and passes full amount on.
#BouncerTime = how long the beams should last
#DoStun = 1 if you want to stun then affected target, mainly for an ion storm
#BounceCount = do not set.  It is precedurally generated by the script to count the number of jumps that have been done.

#remember to import the entity:
#local BounceMarker = import('/mods/seiyaunits/entities/BounceMarker/BounceMarker.lua')
#to start the process, create the following at your target and attach to the target, or move it to the center of the lightshow
#local childMarker = BounceMarker(CreateBouncerSpec(TargetRadius, TargetNumber, BounceDamage, FullDamage, BouncerTime, DoStun, AttackBeams))

CreateBouncerSpec = function(Parent, targetradius, targetnumber, bouncenumber, damage, fulldamage, bouncertime, dostun, stuntime, attackbeams)
  return{
    parent = Parent, 
    TargetRadius = targetradius or 5, 
    TargetNumber = targetnumber or 0,
    BounceNumber = bouncenumber or 0,
    BounceDamage = damage or 1000,
    FullDamage = fulldamage or 0,
    BouncerTime = bouncertime or 5,
    DoStun = dostun or 0,
    StunTime = stuntime or 1,
#    AttackBeams = attackbeams or {'/effects/emitters/seraphim_othuy_beam_01_emit.bp'},
    AttackBeams = attackbeams or EffectTemplate.SUltraChromaticBeamGeneratorBeam,
  }
end


BounceMarker = Class(Entity) {

OnDestroy = function(self)
    self.Trash:Destroy()
end,

OnCreate = function(self, spec)

  self.DoBreak = false


#create a trashbag
  if not self.Trash then
    self.Trash = TrashBag()
  end

#Do variable initializations

  self.TargetList = {}
  if spec.parent then
    parent = spec.parent
  else
    LOG('DEBUG: Bouncer has no parent.  You need to write better checks.')
  end
  BounceNumber = spec.BounceNumber
  if BounceNumber == 0 then
    BounceNumber = 10000
  end

  TargetNumber = spec.TargetNumber or 0
  if TargetNumber == 0 then
    TargetNumber = 100000
  end


  TargetRadius = spec.TargetRadius or 15
  BounceDamage = spec.BounceDamage or 1000
  FullDamage = spec.FullDamage or 0
  BouncerTime = spec.BouncerTime or 5
  DoStun = spec.DoStun or 0
  StunTime = spec.StunTime or 1
  AttackBeams = spec.AttackBeams or {'/effects/emitters/seraphim_othuy_beam_01_emit.bp'}

  #initialize all our handler threads
  ForkThread(self.jibakuthread, self, BouncerTime)
#  self:ForkThread(self.slavethread, self)
  ForkThread(self.targetThread, self, parent, TargetRadius, TargetNumber, BounceDamage, FullDamage, BouncerTime, DoStun, AttackBeams)
  ForkThread(self.WarpTarget, self, self.warptarget)
end,



#make our timer thread to suicide after a certain amount of time
jibakuthread = function(self, BouncerTime)
  WaitSeconds(5)
  for k,v in self.TargetList do
    v.Bounced = false
  end
  self:Destroy()
end,




#watch to make certain that our target hasnt died on us.  Is this still necessary?
slavethread = function(self)
  WaitSeconds(1) 
  if self.target:IsDead() then
    LOG('DEBUG: Killing myself cause of slavery.')
    self:Destroy()
  end
end,



#beam attachment and removal thread.
BeamThread = function(self, AttackBeams, childMarker, army)

 while true do
  local beams = {}
  for k, v in AttackBeams do
    local beam = AttachBeamEntityToEntity(childMarker, -1, self, -2, army, v)
    table.insert(beams, beam)
    self.Trash:Add(beam)
  end

  WaitTicks(1)
  for k, v in beams do
    #LOG(repr(k))
    #LOG(repr(v))
    v:Destroy()
  end
 end
end,

WarpTarget = function(self, warptarget)
  while true do
    if not warptarget or warptarget:IsDead() then
#      LOG('DEBUG: Something odd with this target')
      break
    end
    Warp(self, warptarget:GetPosition())
    WaitTicks(1)
  end
end,

  
#The main workhorse thread.  Get new targets if we are not done bouncing and spawn new markers.
targetThread = function(self, parent, TargetRadius, TargetNumber, BounceDamage, FullDamage, BouncerTime, DoStun, AttackBeams)
  local targets = {}

#check to see if this is the first bounce marker, if it is, create our bounce counter, if it is not, increment it. ##Not implemented yet.
  if not self.BounceCount then
    self.BounceCount = 1
  else
    self.BounceCount = self.BounceCount + 1
  end


#check if we have hit the end of the line on bounces
  if self.BounceCount <= BounceNumber then
    if self:GetPosition() == {0,0,0} then
      LOG('DEBUG: Need to correct position faster')
    end
    targetlist = utilities.GetEnemyUnitsInSphere(self, self:GetPosition(), TargetRadius)

    for k,v in targetlist do
      local dist = VDist3(self:GetPosition(),v:GetPosition())
      targets[dist] = v
    end


    if targets then
      local targetCount = 0
      for k, v in targets do
        LOG('DEBUG: Target - ' .. k)
        local target = v

        table.insert(self.TargetList, target)
        if not target.Bounced or target.Bounced == false then
          target.Bounced = true
          if not FullDamage or FullDamage == 0 then
            NextDamage = BounceDamage - target:GetHealth()
          else
            NextDamage = BounceDamage
          end
          if NextDamage > 0 then
            local childMarker = BounceMarker(CreateBouncerSpec(parent, TargetRadius, TargetNumber, BounceNumber, NextDamage, FullDamage, BouncerTime, DoStun, StunTime, AttackBeams))
            childMarker.warptarget = target
            Warp(childMarker, target:GetPosition())
            local warpthread = ForkThread(childMarker.WarpTarget, self, target)
            local beams = ForkThread(self.BeamThread, self, AttackBeams, childMarker, self:GetArmy())
            childMarker.BounceCount = self.BounceCount
            childMarker.Trash:Add(warpthread)
            self.Trash:Add(beams)
            targetCount = targetCount + 1
          end
          if DoStun == 1 then
            target:SetStunned(StunTime)
          end
          local targetLife = target:GetHealth()
          if targetLife < BounceDamage then
            if target:IsDead() then
              targetlife = 1
            end
            Damage(parent, {0,0,0},  target, targetLife, 'normal') 
          else
            Damage(parent, {0,0,0},  target, BounceDamage, 'normal') 
          end
        else
#          LOG('DEBUG: Already hit')
        end
        if targetCount >= TargetNumber then
          break
        end
      end
    end
  end
end,
}