local anom_list=nil
local cur_level=nil

local radius={
    zone_buzz=1,
    zone_buzz_weak=1,
    zone_buzz_average=1,
    zone_buzz_strong=2,
    zone_gravi_zone=7,
    zone_gravi_zone_weak=6,
    zone_gravi_zone_weak_noart=6,
    zone_gravi_zone_average=6,
    zone_gravi_zone_strong=6,
    zone_gravi_zone_killing=7,
    zone_mincer=7,
    zone_mincer_weak=7,
    zone_mincer_weak_noart=7,
    zone_mincer_average=7,
    zone_mincer_strong=7,
    zone_mosquito_bald=7,
    zone_mosquito_bald_weak=6,
    zone_mosquito_bald_weak_noart=7,
    zone_mosquito_bald_average=7,
    zone_mosquito_bald_strong=7,
    zone_mosquito_bald_strong_noart=7,
    zone_sarcofag=5,
    zone_witches_galantine=6,
    zone_witches_galantine_weak=6,
    zone_witches_galantine_average=6,
    zone_witches_galantine_strong=7,
    zone_zharka_static=5,
    zone_zharka_static_weak=5,
    zone_zharka_static_average=5,
    zone_zharka_static_strong=5,
    zone_mine_field=2,
    zone_death=2
  }

function get_radius_for_section(sect)
  if radius[sect] then
    return radius[sect]
  else
    mylog("cannot find radius for " .. sect)
    return 4
  end
end

function add_anomaly(id,cls,sect,rad)
  if anom_list==nil then
    anom_list={}
  end
  if cur_level~=level.name() then
    anom_list={}
    cur_level=level.name()
--    mylog("switching to level " .. tostring(cur_level) )
  end
--  mylog("adding " .. id .. " clsid " .. cls .. " " .. sect )
  anom_list[id]={pos=0,clsid=cls,radius=rad or get_radius_for_section(sect),section=sect}
end

function remove_anomaly(id)
  if anom_list then
    anom_list[id]=nil
  end
end


function enumerate_anoms()
  if cur_level~=level.name() then
    anom_list=nil
    cur_level=level.name()
  end
  if not anom_list then
    anom_list={}
    local cnt=0
--    mylog(clsid.zone_bfuzz_s .. " " .. 
--          clsid.zone_galant_s .. " " ..
--          clsid.zone_mbald_s .. " " ..
--          clsid.zone_mincer_s)
    for id=1,40000,1 do
      local obj=level.object_by_id(id)
      if obj then
        if obj:clsid()==clsid.zone_bfuzz_s or
            obj:clsid()==clsid.zone_galant_s or
            obj:clsid()==clsid.zone_mbald_s or
            obj:clsid()==clsid.zone_mincer_s then
          anom_list[id]={object=obj,pos=obj:position(),clsid=obj:clsid()}
          local pos=anom_list[id].pos
--          mylog("found " .. id .. " " .. obj:clsid() .. " at " .. pos.x .. ";" .. pos.y .. ";" .. pos.z )
          cnt=cnt+1
        else
--        mylog(obj:clsid())
        end
      end
    end
--    mylog("total " .. cnt)
    if cnt==0 then
      anom_list=nil
    end
  end
end

function get_nearest_anomaly(npc,dirp)
  local posn=npc:position()
  local dir
  local anomid=nil
  local mindist=10000000
  local pos1=nil
  local cls=0
  local cnt=0
  local anomdesc={}
  if dirp then
    dir=dirp
  else
    dir=npc:direction()
  end
  for id,o in pairs(anom_list) do
    if o then
      if o.pos==0 then
        local obj=level.object_by_id(id)
        if obj then
          o.pos=obj:position()
--          mylog("reposition " .. id .. " clsid " .. obj:clsid() ..  " at " .. o.pos.x .. ";" .. o.pos.y .. ";" .. o.pos.z )
        end
      end
      if o.pos~=0 then
        cnt=cnt+1
        local delta=vector():set(o.pos):sub(posn)
        local scalarmul=(delta.x*dir.x+delta.z*dir.z)/math.sqrt(delta.x*delta.x+delta.z*delta.z) 
    -- если скалярное произведения текущего направления движения NPC
    -- и относительного радиус вектора аномалии меньше 0, то NPC удаляется от аномалии
        if scalarmul>-0.4 then
          local dist=posn:distance_to(o.pos)-o.radius
--    if id>20000 then
--      mylog("get nearest " .. npc:name() .. " dist " .. dist)
--    end
          if dist<mindist then
            mindist=dist
            anomid=id
            pos1=o.pos
            cls=o.clsid
            anomdesc=o
          end
        end
      end
    end
  end
--  if anomid then
--    mylog("get nearest " .. anomid .. " dist " .. mindist)
--  end
  if anomid then
    return true,anomid,pos1,cls,mindist+anomdesc.radius,anomdesc.radius,anomdesc.section
  else
    return false
  end
end
