require('o_mis')
require('State')

function onStartup(self)


     --###########################################################
     --########## Set Variables 
     --###########################################################
     self:SetVar("REBUILD_STATE", "null")
     
     self:SetProximityRadius { radius = 20 , name = "aggroRadius" }
     self:SetProximityRadius { radius = 50 , name = "resetRadius" }
     storeHomePoint(self)
     -- Start Break timer -- 
     GAMEOBJ:GetTimer():AddTimerWithCancel( 10, "BreakStart",self )	
     GAMEOBJ:GetTimer():AddTimerWithCancel( 8, "BreakBase",self )	
     local pos = getHomePoint(self)
     RESMGR:LoadObject { objectTemplate =  3086 , x= pos.x   , y= pos.y , z= pos.z  , owner = self } -- Student 1
     
     self:UseStateMachine{} 
     
     --###########################################################
     --########## STATES
     --###########################################################
     
      Idle = State.create()
      Idle.onEnter = function(self)
           
            
      end 
      Idle.onArrived = function(self)
             
      end  

    --###########################################################
    --########## TETHER
    --###########################################################
    tether = State.create()
    tether.onEnter = function(self)
       -- Rebuild Reset -- 
       self:RebuildReset()
    end    
    tether.onArrived = function(self,msg)

    end

    --###########################################################
    --########## AGGRO
    --###########################################################   
    aggro = State.create()
    -- Aggro onEnter
    aggro.onEnter = function(self)
        local INITIAL_ATTACK_TIME = 1
        -- Start the heartbeat
        self:SetVar("readyToAttack", false)
        GAMEOBJ:GetTimer():AddTimerWithCancel(  INITIAL_ATTACK_TIME , "AttackHeartBeat", self )
              
        local myPos = getHomePoint(self)
        local target = getMyTarget(self)
        
        if  target:IsDead().bDead  then
            setState("tether",self)     
        else
            self:SetTetherPoint { tetherPt = myPos,radius = 60 }
            self:FollowTarget { targetID = target, radius = 15 ,speed = 0 , keepFollowing = true }       
        end
            
      
    end -- end function
    
    
    aggro.onTimerDone = function(self, msg)
          if msg.name == "AttackHeartBeat" then
            self:SetVar("readyToAttack", true)
            DoAttack(self);
            local castTime = 1
           
            GAMEOBJ:GetTimer():AddTimerWithCancel(  castTime , "AttackHeartBeat", self )
        else
            onTimerDone(self, msg)
        end
    end
    
    aggro.onArrived = function(self, msg)
            DoAttack(self)
    end
    
    aggro.onExit = function(self)
        GAMEOBJ:GetTimer():CancelTimer("AttackHeartBeat", self)
    end
  
    -- This will be called if FollowTarget fails.  That would only fail because the target has died or logged out.  In any case, the target was lost
    aggro.onCancelled = function(self, msg)
        setState("tether",self)
    end
					
    function DoAttack(self)
        if(self:GetVar("readyToAttack") == false) then
            return
        end
        
        if CanAttackTarget(self) then
            self:SetVar("readyToAttack", false)
            
            if self:GetVar("MaxTableSkill") == nil then
                for i = 1, table.maxn (self:GetSkills().skills) do  
                    self:SetVar("MaxTableSkill", i ) 
                end 
                
            end 
 
                self:CastSkill{skillID = self:GetSkills().skills[self:GetVar("MaxTableSkill")] } 
        
        end
    end
    
      addState(Idle, "Idle", "Idle", self)
      addState(tether, "tether", "tether", self)
      addState(aggro, "aggro", "aggro", self)
      beginStateMachine("Idle", self) 

end
    --###########################################################
    --########## CAN ATTACK
    --###########################################################
function CanAttackTarget(self)
    local myTarget = getMyTarget(self)
    local range = 12
    local myPos = Vector.new(self:GetPosition().pos)
    local hisPos = Vector.new(myTarget:GetPosition().pos)
    local dist = hisPos - myPos
    
   if not myTarget:Exists() or myTarget:IsDead().bDead then
      setState("tether",self)
      return false
   end
   
   if self:GetVar("REBUILD_STATE") == "broke" then
     return false
   end
   
    -- If we are close enough and if the object is in the FOV, then attack
    if dist:sqrLength() <= range * range then --and (self:IsObjectInFOV { target = myTarget, radius = 5 , minRange = 0, maxRange = 100 }.result) then
            return true
    end
    return false
    
end -- end CanAttackTarget 
    --###########################################################
    --########## PROXIMITY
    --###########################################################   
    

     
     
function onProximityUpdate(self, msg)
      if msg.objType == "Enemies" or msg.objType == "NPC" or msg.objType == "Rebuildables" and  msg.objId:GetFaction().faction == 1 and  self:GetVar("REBUILD_STATE") ~= "broke" and msg.status == "ENTER" and msg.name == "aggroRadius" then
        storeTarget(self, msg.objId)
        setState("aggro", self) 
      end 
      if msg.objType == "Enemies" or msg.objType == "NPC" or msg.objType == "Rebuildables" and  msg.objId:GetFaction().faction == 1 and  self:GetVar("REBUILD_STATE") ~= "broke" and msg.status == "EXIT" and msg.name == "resetRadius" then
         local pet = getPet(self, "Child" , 1 )
         pet:Die{ killType = "SILENT" }
          GAMEOBJ:GetTimer():AddTimerWithCancel( 2, "BreakStart",self  )
      end       
      
end
    --###########################################################
    --########## REBUILD NOTIFY
    --###########################################################
function onRebuildNotifyState(self, msg)
	if (msg.iState) == 2 then
	 GAMEOBJ:GetTimer():AddTimerWithCancel( 2, "SpawnBase",self )	
	 self:SetVar("REBUILD_STATE", "null")
	end
	
	if (msg.iState) == 4 then -- Cancle
	     self:SetImmunity{ immunity = true }
	     self:SetVar("REBUILD_STATE", "broke")
	end
end   
    --###########################################################
    --########## ON HIT
    --###########################################################
function onOnHit(self,msg)   
   hp = self:GetHealth{}.health
    print("health ="..hp)
    if hp < 7 then
     storeTarget(self, msg.attacker)
     GAMEOBJ:GetTimer():AddTimerWithCancel( 2, "BreakStart",self )	
 
     local pet = getPet(self, "Child" , 1 )
     pet:Die{ killType = "SILENT"}
     setState("aggro", self) 
    end 
end
    --###########################################################
    --########## CHILD LOADED
    --###########################################################
onChildLoaded = function(self,msg)
       
         storePet(self, msg.childID, "Child" , 1 )
                
end 

    --###########################################################
    --########## TIMER
    --###########################################################
onTimerDone = function(self, msg)

    if msg.name == "BreakStart" then 
         self:SetVar("REBUILD_STATE", "broke")
         self:RebuildReset()
         self:SetImmunity{ immunity = true }
         self:SetHealth{ health = 10 }

    end
    if msg.name == "BreakBase" then
         local pet = getPet(self, "Child" , 1 )
         pet:Die{ killType = "SILENT" }
          
    end
    
    if msg.name == "SpawnBase" then
       local pos = getHomePoint(self)
       RESMGR:LoadObject { objectTemplate =  3086 , x= pos.x   , y= pos.y , z= pos.z  , owner = self } -- Student 1
       self:SetImmunity{ immunity = false }
    end  

end 