require "Insurgent/InsurgentTraitDefinitions"

UndyingTrait = CreateInsurgentTrait()
UndyingTrait.name = "Undying"
UndyingTrait.insurgentExclusive = true

function UndyingTrait.Create()
    return TraitFactory.addTrait("Undying", getText("UI_trait_Undying"), 10, getText("UI_trait_UndyingDesc"), false, false)
end

local deathResistLines = {};
local deathNoResistLines = {};

local function GetUndyingLine(_onCooldown)
    if _onCooldown == true then
        local index = ZombRand(5) + 1
        if deathNoResistLines[index] == nil then return "UNDYING!" end
        return deathNoResistLines[index]
    end
    local index = ZombRand(10) + 1
    if deathResistLines[index] == nil then return "UNDYING!" end
    return deathResistLines[index]
end

local function InitUndyingVoiceLines()
    local voiceLineCount = 10;
    for i=1, voiceLineCount do
        table.insert(deathResistLines, getText("UI_trait_UndyingLine"..i));
    end
    local voiceLineCountWeak = 10;
    for i=1, voiceLineCountWeak do
        table.insert(deathNoResistLines, getText("UI_trait_UndyingWeakLine"..i));
    end
end

function UndyingTrait.OnNewGame(player)
    if not player:HasTrait("Undying") then
        return
    end

    local playerdata = player:getModData()
    playerdata.willResistDeath = true;
    playerdata.undyingCooldown = 0;
end

function UndyingTrait.OnGameStart(player)
    InitUndyingVoiceLines()
end

function UndyingTrait.OnPlayerUpdate(player)
    if not player:HasTrait("Undying") then
        return
    end
    local playerdata = player:getModData()
    UndyingTrait.ResistDeath(player, playerdata)
end

function UndyingTrait.ResistDeath(player, playerdata)
    local stats = player:getStats()
    
    if player:getBodyDamage():getHealth() <= 10 then
        if playerdata.willResistDeath then
            for i = 0, player:getBodyDamage():getBodyParts():size() - 1 do
                local b = player:getBodyDamage():getBodyParts():get(i)
                b:RestoreToFullHealth()
            end
            stats:setAnger(1);
            playerdata.willResistDeath = false;
            playerdata.undyingCooldown = 3;

            local zeds = player:getSpottedList()
            if zeds:size() > 0 then
                for i = 0, zeds:size() - 1 do
                    if zeds:get(i):isZombie() then
                        if zeds:get(i):DistTo(player) <= 1.5 then
                            zeds:get(i):knockDown(false)
                        end
                    end
                end
            end
            if getCore():getOptionMusicVolume() ~= 0 then
                getSoundManager():playMusic(MusicChoices.get(100))
            end
            player:Say(GetUndyingLine(false))
        else
            player:Say(GetUndyingLine(true))
        end
    end
end

function UndyingTrait.OnDawn()
    local players = IsoPlayer.getPlayers()
	for i=0,players:size()-1 do
		local player = players:get(i)
		if player and player:isLocalPlayer() and not player:isDead() and player:HasTrait("Undying") then
            UndyingTrait.ResetCooldown(player)
        end
    end
end

function UndyingTrait.ResetCooldown(player)
    local playerdata = player:getModData();
    if not playerdata.willResistDeath then
        for i = 0, player:getBodyDamage():getBodyParts():size() - 1 do
            if player:getBodyDamage():getBodyParts():get(i):getHealth() < 90 then
                return;
            elseif player:getBodyDamage():getBodyParts():get(i):bleeding() then
                return;
            end
        end
        if playerdata.undyingCooldown > 0 then
            playerdata.undyingCooldown = playerdata.undyingCooldown - 1
        else
            playerdata.willResistDeath = true;
        end
    end
end

function UndyingTrait.RegisterEvents()
    Events.OnNewGame.Add(UndyingTrait.OnNewGame)
    Events.OnGameStart.Add(UndyingTrait.OnGameStart)
    Events.OnPlayerUpdate.Add(UndyingTrait.OnPlayerUpdate)
    Events.OnDawn.Add(UndyingTrait.OnDawn)
end
