---@diagnostic disable: undefined-doc-name, undefined-field, undefined-global
AbilityTable = {}
AbilityTable.energyStored = 150;
AbilityTable.energyRegenRate = 1 -- Energy Regenerates at x per second
AbilityTable.energyStoredMax = 150 -- "Fun"

AbilityTable.casterShip = nil --EVI stands for Extended Virtual Intelligence
AbilityTable.gameActive = false
AbilityTable.chargeActive = false

AbilityTable.abilityNames = {"Hack","Missile Mines","Anti Capital Missile Barrage","Deploy Turret"}

--#region Ability Functions
AbilityTable[1] = {}
AbilityTable[1].abilityReady = false
AbilityTable[1].abilityAllowed = false
AbilityTable[1].abilityName = "Hack"
---This function tells your AI ally to hack a hostile ship, this ship will assist you until it's death or 30 seconds have passed. Only applies to NTF and Shieven Fighters (Excluding Dragons) Can start another hack afther the previous ship is destroyed
---@param target ship Ship To Hack
AbilityTable[1].ability = function(target,player)
    if target:isValid() and target:getBreedName() == "Ship" and AbilityTable[1].abilityReady then
        if player.Team:attacks(target.Team)and target.Class.Type.Name == "Fighter" and player.Position:getDistance(target.Position) < 7500 then
            async.run(function()
                local targetTeam = nil
                local hackSuccess = false
                AbilityTable[1].abilityReady = false
                --Attempt the hack over and over
                while true do
                    if AbilityTable.energyStored > 6 and target:isValid() and AbilityTable.casterShip:isValid() then
                        AbilityTable.energyStored = AbilityTable.energyStored - 6
                        local orient = ((target.Position + (target.Physics.Velocity * 0.1)) - AbilityTable.casterShip.Position):getNormalized():getOrientation()
                        local charge = mn.createWeapon(tb.WeaponClasses["Hacking Beam"], orient, AbilityTable.casterShip.Position)
                        charge.Parent = AbilityTable.casterShip
                        charge.Team = mn.Teams["Friendly"]
                        if math.random(0,10) > 9 then
                            mn.sendPlainMessage("Hack Success")
                            hackSuccess = true
                            break;
                        end
                    else break
                    end
                    async.await(mn.waitAsync(1))
                end

                
                if hackSuccess == true then
                    if target:isValid() then
                        targetTeam = target.Team
                        target.Team = mn.Teams["Friendly"]
                        mn.runSEXP("( set-player-orders !"..target.Name.."! (false) !Destroy my target! !Disable my target! !Disarm my target! !Protect my target! !Ignore my target! !Form on my wing! !Cover me! !Engage enemy! !Capture my target! !Rearm me! !Abort rearm! !Stay near me! !Stay near my target! !Keep safe! !Depart! !Destroy subsystem!)")
                        target:giveOrder(ORDER_ATTACK_ANY)

                    end

                    for i = 1, 10, 1 do
                        if target:isValid() then
                            async.await(mn.waitAsync(1))
                        else 
                            break 
                        end
                    end

                    AbilityTable[1].abilityReady = true

                    for i = 1, 20, 1 do
                        if target:isValid() then
                            async.await(mn.waitAsync(1))
                        else break 
                        end
                    end

                    if target:isValid() then
                        target.Team = targetTeam
                        target.kill(target)
                    end
                else
                    async.await(mn.waitAsync(10))
                    AbilityTable[1].abilityReady = true
                end

            end)
        end
    end
end

AbilityTable[2] = {}
AbilityTable[2].abilityReady = false
AbilityTable[2].abilityAllowed = false
AbilityTable[2].abilityName = "Missile Mines"
---This function tells your AI ally to drop missile mines 10 mines are dropped Each mine houses 3 missiles Mines last 100 seconds
---@param target ship Ship To Hack
AbilityTable[2].ability = function(target,player)
    if AbilityTable[2].abilityReady and AbilityTable.energyStored > 60 then
        AbilityTable[2].abilityReady = false
        AbilityTable.energyStored = AbilityTable.energyStored - 60
	    async.run(function()
            for i = 1, 10, 1 do
                if AbilityTable.casterShip:isValid() and player:isValid() then
                    spawnMissile(AbilityTable.casterShip, "Ax1Mine", player)
                    async.await(mn.waitAsync(0.5))
                else break
                end
            end
            async.await(mn.waitAsync(20))
            AbilityTable[2].abilityReady = true
        end)
    end
end

AbilityTable[3] = {}
AbilityTable[3].abilityReady = false
AbilityTable[3].abilityAllowed = false
AbilityTable[3].abilityName = "Anti Capital Missile Barrage"
---This function tells your AI ally to launch an anti-capship missile barrage of three missiles against the target (only if a capital ship)
---@param target ship Ship To launch missiles at
---@param player ship Player's Ship
AbilityTable[3].ability = function(target,player)
	if target:isValid() and target:getBreedName() == "Ship" and AbilityTable[3].abilityReady and player.Team:attacks(target.Team) and AbilityTable.energyStored > 60 then
        AbilityTable[3].abilityReady = false
        AbilityTable.energyStored = AbilityTable.energyStored - 60
        async.run(function() 
            for i = 1, 3, 1 do
                if AbilityTable.casterShip:isValid() and player:isValid() then
                    local newIri = mn.createWeapon(tb.WeaponClasses["Cyclops"],  (AbilityTable.casterShip:getfvec() *-1):getOrientation(), AbilityTable.casterShip.Position + AbilityTable.casterShip:getfvec()*-20) -- + (mat:getFvec() * 10))
                    newIri.Parent = player
                    newIri.Team = player.Team
                    newIri.Target = target
                    async.await(mn.waitAsync(1))
                else break
                end
            end

            async.await(mn.waitAsync(17))
            AbilityTable[3].abilityReady = true
        end)

	end
end

AbilityTable[4] = {}
AbilityTable[4].abilityReady = false
AbilityTable[4].abilityAllowed = false
AbilityTable[4].abilityName = "Deploy Turret"
---This function tells your AI ally to deploy a temporary turret that lasts 120 seconds. Can deploy a new turret every 20 seconds
---@param target ship Ship To Hack
---@param player ship Player's Ship
AbilityTable[4].ability = function(target,player)
	if AbilityTable[4].abilityReady and AbilityTable.energyStored > 90 and AbilityTable.casterShip:isValid() and player:isValid() then
        AbilityTable[4].abilityReady = false
        local newShip = mn.createShip("Turret#"..math.random(0,100000),tb.ShipClasses["GTSG Watchdog"],AbilityTable.casterShip.Orientation,AbilityTable.casterShip.Position + AbilityTable.casterShip:getfvec()*-20)
        newShip.Team = player.Team
        AbilityTable.energyStored = AbilityTable.energyStored - 90

        async.run(function()
            async.await(mn.waitAsync(20))
            AbilityTable[4].abilityReady = true
            async.await(mn.waitAsync(100))

            if newShip:isValid() then
                newShip.kill(newShip)
            end
        end)
	end
end
--#endregion

---This function handles the regeneration of the limited energy pool
AbilityTable.RegenerateEnergy = function()
    async.run(function() 
        while AbilityTable.chargeActive do
            if AbilityTable.energyStored < AbilityTable.energyStoredMax and AbilityTable.energyRegenRate > 0 then
                AbilityTable.energyStored = AbilityTable.energyStored + 1
            end
            async.await(mn.waitAsync(1/AbilityTable.energyRegenRate))
        end
    end)
end

---Function Handles the mine Script checking (every 0.25 seconds)
AbilityTable.missileMinesRequirement = function()
    async.run(function()
        while true do
            if hv.Player:isValid() then
                mineFunction("Ax1Mine",1000,"Ax1MineMissile",3)
            end
            async.await(mn.waitAsync(0.25))
        end
    end)
end

--#region Startup and Unlock Abilities SEXPS
mn.LuaSEXPs["lua-SHIPAbilities-set-enabled"].Action = function(energyStoredMax,energyStored,energyRegenRate,ship,startUI)
    AbilityTable.energyStored = energyStored;
	AbilityTable.energyRegenRate = energyRegenRate -- Energy Regenerates at x per second
	AbilityTable.energyStoredMax = energyStoredMax -- "Fun"

    AbilityTable.gameActive = startUI
	AbilityTable.casterShip = ship
    AbilityTable.chargeActive = true

    --Update others if need be
    AbilityTable[1].abilityReady = true
    AbilityTable[2].abilityReady = true
    AbilityTable[3].abilityReady = true
    AbilityTable[4].abilityReady = true

    --Activate Energy Regeneration
    AbilityTable.RegenerateEnergy()
    AbilityTable.missileMinesRequirement()
end

mn.LuaSEXPs["lua-SHIPAbilities-set-disabled"].Action = function()
    AbilityTable.gameActive = false
end

mn.LuaSEXPs["lua-SHIPAbilities-set-Abilities"].Action = function(hack,mines,SlowMissileBarrage,TurretDeployment)
    AbilityTable[1].abilityAllowed = hack
    AbilityTable[2].abilityAllowed = mines
    AbilityTable[3].abilityAllowed = SlowMissileBarrage
    AbilityTable[4].abilityAllowed = TurretDeployment
end
--#endregion

--#region RETURN SEXPS
---This function checks if an ability is ready to be deployed (Energy checked seperately)
---@param abilityNumber number
---@return boolean
mn.LuaSEXPs["lua-Areturn-abilityReady"].Action = function(abilityNumber)
    if AbilityTable[abilityNumber].abilityReady then
        return true
    else
        return false
    end
end

---This function gets the amount of energy stored within the system
---@return number
mn.LuaSEXPs["lua-Areturn-EnergyStored"].Action = function()
    return AbilityTable.energyStored
end

---This function gets if the energy stored is equal to the max energy
---@return boolean
mn.LuaSEXPs["lua-Areturn-isEnergyMax"].Action = function()
    if AbilityTable.energyStored == AbilityTable.energyStoredMax then
        return true
    else
        return false
    end
end
---This function returns the max amount of energy that can be stored
---@return number
mn.LuaSEXPs["lua-Areturn-MaxEnergy"].Action = function()
    return AbilityTable.energyStoredMax
end
--#endregion


AbilityTable.keyPress = function(keyNumber)
    if AbilityTable.gameActive and AbilityTable[keyNumber].abilityAllowed then
        AbilityTable[keyNumber].ability(hv.Player.Target,hv.Player)
    end
end

---This function activates an ability aimed at a targeted ship (requires the same checks that the player goes through - abilityUnlocked)
---@param number any
---@param ship any
mn.LuaSEXPs["lua-Abilities-activate-ability"].Action = function(number,ship)
    AbilityTable[number].ability(ship,hv.Player)
end