--luacheck: ignore
local biter_waves = require 'maps.wave_of_death.biter_waves'
local ai = {}

ai.spawn_wave = function (surface, lane_number, wave_number, amount_modifier)
    local is_spread_wave = true
    if amount_modifier == 1 then
        is_spread_wave = false
    end

    if not storage.loaders[lane_number].valid then
        return
    end

    local x_modifier = 32 - math.random(0, 64)

    local spawn_position = { x = storage.loaders[lane_number].position.x + x_modifier, y = storage.loaders[lane_number].position.y - 288 }

    local unit_group = surface.create_unit_group({ position = spawn_position, force = 'enemy' })

    for _, biter_type in pairs(biter_waves[wave_number]) do
        for count = 1, math.floor(biter_type.amount * amount_modifier), 1 do
            local pos = surface.find_non_colliding_position(biter_type.name, spawn_position, 96, 3)
            local biter = surface.create_entity({ name = biter_type.name, position = pos, force = 'enemy' })
            storage.wod_biters[biter.unit_number] = { entity = biter, lane_number = lane_number, spread_wave = is_spread_wave }
            unit_group.add_member(biter)
            if not is_spread_wave then
                storage.wod_lane[lane_number].alive_biters = storage.wod_lane[lane_number].alive_biters + 1
            end
        end
    end

    unit_group.set_command(
        {
            type = defines.command.compound,
            structure_type = defines.compound_command.return_last,
            commands = {
                {
                    type = defines.command.attack_area,
                    destination = { x = storage.loaders[lane_number].position.x + x_modifier, y = storage.loaders[lane_number].position.y },
                    radius = 32,
                    distraction = defines.distraction.by_enemy
                },
                {
                    type = defines.command.attack,
                    target = storage.loaders[lane_number],
                    distraction = defines.distraction.by_enemy
                }
            }
        }
    )

    if is_spread_wave then
        return
    end
    storage.wod_lane[lane_number].current_wave = storage.wod_lane[lane_number].current_wave + 1

    local m = 0.005
    if storage.wod_lane[lane_number].current_wave > #biter_waves then
        m = 0.25
    end
    storage.biter_evasion_health_increase_factor = storage.biter_evasion_health_increase_factor + m

    for _, player in pairs(game.connected_players) do
        create_lane_buttons(player)
    end
end

--on_entity_died event
ai.spawn_spread_wave = function (event)
    local entity = event.entity
    if not entity.unit_number then
        return
    end
    if not storage.wod_biters[entity.unit_number] then
        return
    end
    if storage.wod_biters[entity.unit_number].spread_wave then
        storage.wod_biters[entity.unit_number] = nil
        return
    end

    local trigger_lane_number = storage.wod_biters[entity.unit_number].lane_number

    storage.wod_lane[trigger_lane_number].alive_biters = storage.wod_lane[trigger_lane_number].alive_biters - 1
    if storage.wod_lane[trigger_lane_number].alive_biters ~= 0 then
        return
    end

    for lane_number = 1, 4, 1 do
        if lane_number ~= trigger_lane_number then
            if #game.forces[lane_number].players > 0 and storage.wod_lane[lane_number].game_lost == false then
                ai.spawn_wave(entity.surface, lane_number, storage.wod_lane[trigger_lane_number].current_wave - 1, storage.spread_amount_modifier)
            end
        end
    end

    --game.print("Lane #" .. trigger_lane_number .. " has defeated their wave.")
end

--on_entity_rotated event
ai.trigger_new_wave = function (event)
    local entity = event.entity
    if entity.name ~= 'loader' then
        return
    end
    if game.tick < 18000 then
        entity.force.print('>> It is too early to call waves yet.', { r = 180, g = 0, b = 0 })
        return
    end
    if #game.players < 4 then
        entity.force.print('>> More players are required to spawn waves.', { r = 180, g = 0, b = 0 })
        return
    end
    local lane_number = tonumber(entity.force.name)
    if not storage.wod_lane[lane_number] then
        return
    end
    if storage.wod_lane[lane_number].alive_biters > 0 then
        entity.force.print('>> There are ' .. storage.wod_lane[lane_number].alive_biters .. ' spawned biters left.', { r = 180, g = 0, b = 0 })
        return
    end

    local wave_number = storage.wod_lane[lane_number].current_wave
    if not biter_waves[wave_number] then
        wave_number = #biter_waves
    end
    ai.spawn_wave(entity.surface, lane_number, wave_number, 1)

    local player = game.players[event.player_index]
    for _, force in pairs(game.forces) do
        if force.name == entity.force.name then
            force.print('>> ' .. player.name .. ' has summoned wave #' .. storage.wod_lane[lane_number].current_wave - 1 .. '', { r = 0, g = 100, b = 0 })
        else
            force.print('>> Lane ' .. entity.force.name .. ' summoned wave #' .. storage.wod_lane[lane_number].current_wave - 1 .. '', { r = 0, g = 100, b = 0 })
        end
    end

    for _, player in pairs(game.connected_players) do
        player.play_sound { path = 'utility/new_objective', volume_modifier = 0.3 }
    end
end

ai.prevent_friendly_fire = function (event)
    if event.cause then
        if event.cause.type == 'unit' then
            return
        end
    end
    if event.entity.name ~= 'loader' then
        return
    end
    event.entity.health = event.entity.health + event.final_damage_amount
end

return ai
