SuR.AI_Nodes = {}

local found_ai_nodes = false
local M = {}
local SIZEOF_INT = 4
local SIZEOF_SHORT = 2
local AINET_VERSION_NUMBER = 37
local function toUShort(b)
    local i = {string.byte(b,1,SIZEOF_SHORT)}
    return i[1] +i[2] *256
end
local function toInt(b)
    local i = {string.byte(b,1,SIZEOF_INT)}
    i = i[1] +i[2] *256 +i[3] *65536 +i[4] *16777216
    if(i > 2147483647) then return i -4294967296 end
    return i
end
local function ReadInt(f) return toInt(f:Read(SIZEOF_INT)) end
local function ReadUShort(f) return toUShort(f:Read(SIZEOF_SHORT)) end

if found_ai_nodes then
    return
end

f = file.Open("maps/graphs/"..game.GetMap()..".ain","rb","GAME")
if not f then
    return
end

found_ai_nodes = true
local ainet_ver = ReadInt(f)
local map_ver = ReadInt(f)
if ainet_ver ~= AINET_VERSION_NUMBER then
    MsgN("Unknown graph file")
    return
end

local numNodes = ReadInt(f)
if numNodes < 0 then
    MsgN("Graph file has an unexpected amount of nodes")
    return
end

for i = 1,numNodes do
    local v = Vector(f:ReadFloat(),f:ReadFloat(),f:ReadFloat())
    local yaw = f:ReadFloat()
    local flOffsets = {}
    for i = 1,NUM_HULLS do
        flOffsets[i] = f:ReadFloat()
    end
    local nodetype = f:ReadByte()
    local nodeinfo = ReadUShort(f)
    local zone = f:ReadShort()
    if nodetype == 4 or nodetype == 3 then
        goto cont
    end
    
    local node = {
        pos = v,
        yaw = yaw,
        offset = flOffsets,
        type = nodetype,
        info = nodeinfo,
        zone = zone,
        neighbor = {},
        numneighbors = 0,
        link = {},
        numlinks = 0
    }

    table.insert(SuR.AI_Nodes,node.pos)
    ::cont::
end

if #SuR.AI_Nodes == 0 then
    hook.Add("Think", "SuR_BlockNode", function()
        SuR:SendDataToClient("GameplayBlockNode", true)
        SuR.Game_Started = false
        SuR.DeployTime = CurTime()+SuR.Config.Delay_Before_Deploy
    end)
end

function SuR:GetRandomPos(underroof, mindist, maxdist)
    local newtab = {}
    local tab = SuR.AI_Nodes
    if #tab > 0 then
        for i=1,#tab do
            local pos = tab[i]
            
            local tr = util.TraceLine({
                start = pos,
                endpos = pos + Vector(0,0,9999),
            })
            if tr.HitSky and underroof or !tr.HitSky and !underroof then continue end

            local visible = false
            local tab = player.GetAll()
            local rndply = tab[math.random(1,#tab)]
            for i=1,#tab do
                local ply = tab[i]
                if ply:IsZombie() then continue end
                if ply:Alive() and ply:IsLineOfSightClear(pos) then
                    visible = true
                    break
                end
                if mindist and maxdist then
                    local dist = ply:GetPos():DistToSqr(pos)
                    if dist < mindist^2 then 
                        visible = true
                        break
                    end
                end
            end
            if IsValid(rndply) and rndply:GetPos():DistToSqr(pos) > maxdist^2 then
                visible = true
            end

            if visible then continue end

            table.insert(newtab, pos)
        end
    end
    if #newtab > 0 then
        return newtab[math.random(1,#newtab)]
    else
        return nil
    end
end