local ZombiePointManager = BaseClass("ZombiePointManager")

function ZombiePointManager:__init()
end

function ZombiePointManager:__delete()
end

function ZombiePointManager:Init(battleMgr)
  self.battleMgr = battleMgr
  self.pointMap = {}
  self.pointList = {}
  self.pointGuid = 1
  self.createList = {}
  self.blockGuidMap = {}
  self.blockSceneMap = {}
end

function ZombiePointManager:Destroy()
  self.battleMgr = nil
  self.pointMap = nil
  self.pointList = nil
  self.createList = nil
  self.blockGuidMap = nil
  self.blockSceneMap = nil
end

local BossIDCoef = 100

function ZombiePointManager:Append(sceneMeta, offset)
  local map = self.pointMap[sceneMeta.id]
  if not map then
    map = {}
    self.pointMap[sceneMeta.id] = map
  end
  if sceneMeta.local_monster_group and sceneMeta.local_monster_group ~= "" then
    local spl = string.split(sceneMeta.local_monster_group, ",")
    for _, point in ipairs(spl) do
      local params = string.split(point, "|")
      if #params == 3 then
        local cfg = map[tonumber(params[1])] or {}
        cfg.guid = self.pointGuid
        cfg.pointId = tonumber(params[1])
        cfg.monsterId = tonumber(params[2])
        cfg.probability = tonumber(params[3])
        cfg.offset = offset
        map[cfg.pointId] = cfg
        self.pointList[cfg.guid] = cfg
        self.pointGuid = self.pointGuid + 1
      end
    end
  end
  if sceneMeta.normal_boss and sceneMeta.normal_boss ~= "" then
    local monsterIds = string.split(sceneMeta.normal_boss, "|")
    for i, mid in ipairs(monsterIds) do
      local cfg = map[2000 + i - 1]
      if cfg and cfg.monsterId == nil then
        cfg.guid = self.pointGuid
        cfg.pointId = 2000 + i - 1
        cfg.monsterId = tonumber(mid)
        cfg.probability = 5000
        cfg.offset = offset
        map[cfg.pointId] = cfg
        self.pointList[cfg.guid] = cfg
        self.pointGuid = self.pointGuid + 1
      end
    end
  end
  if sceneMeta.normal_monster and sceneMeta.normal_monster ~= "" then
    local resPoint = {}
    for k, cfg in pairs(self.pointMap[sceneMeta.id]) do
      if cfg.monsterId == nil then
        table.insert(resPoint, k)
      end
    end
    local spl = string.split(sceneMeta.normal_monster, ",")
    local monsterIds = string.split(spl[1], "|")
    for _ = 1, tonumber(spl[2]) do
      if #resPoint < 1 then
        break
      end
      local pointIdIdx = math.random(#resPoint)
      local cfg = map[resPoint[pointIdIdx]]
      cfg.guid = self.pointGuid
      cfg.pointId = resPoint[pointIdIdx]
      cfg.monsterId = tonumber(monsterIds[math.random(#monsterIds)])
      cfg.probability = 5000
      cfg.offset = offset
      map[cfg.pointId] = cfg
      self.pointList[cfg.guid] = cfg
      self.pointGuid = self.pointGuid + 1
      table.remove(resPoint, pointIdIdx)
    end
  end
  if not string.IsNullOrEmpty(sceneMeta.block_monster) then
    local blockMap = self.blockSceneMap[sceneMeta.id]
    if not blockMap then
      blockMap = {}
      self.blockSceneMap[sceneMeta.id] = blockMap
    end
    local cfg = string.split(sceneMeta.block_monster, "_")
    local prop_raw_cfg = string.split(cfg[1], ",")
    local randomMap = {}
    local p = 0
    for i, rawStr in ipairs(prop_raw_cfg) do
      local spl = string.split(rawStr, "|")
      p = p + tonumber(spl[2])
      randomMap[#randomMap + 1] = {
        id = tonumber(spl[1]),
        probability = p
      }
    end
    local point_raw_cfg = string.split(cfg[2], "|")
    for i, pIndex in ipairs(point_raw_cfg) do
      pIndex = tonumber(pIndex)
      local pCfg = blockMap[pIndex]
      local random = math.random(0, p)
      local targetId = 0
      for _, item in ipairs(randomMap) do
        targetId = item.id
        if random <= item.probability then
          break
        end
      end
      if pCfg and 0 < targetId then
        cfg = blockMap[pIndex]
        cfg.guid = self.pointGuid
        cfg.pointId = pIndex
        cfg.monsterId = targetId
        cfg.offset = offset
        cfg.isBlock = true
        blockMap[cfg.pointId] = cfg
        self.blockGuidMap[cfg.guid] = cfg
        self.pointGuid = self.pointGuid + 1
      end
    end
  end
end

function ZombiePointManager:ConfigMonsterPoint(cfg, sceneMeta)
  local map = self.pointMap[sceneMeta.id]
  if not map then
    map = {}
    self.pointMap[sceneMeta.id] = map
  end
  local point = map[cfg.max_blood]
  if not point then
    point = {}
    map[cfg.max_blood] = point
  end
  point.pos = Vector3.New(cfg.t.x, cfg.t.y, cfg.t.z)
end

function ZombiePointManager:ConfigBlockPoint(cfg, sceneMeta)
  local map = self.blockSceneMap[sceneMeta.id]
  if not map then
    map = {}
    self.blockSceneMap[sceneMeta.id] = map
  end
  local point = map[cfg.max_blood]
  if not point then
    point = {}
    map[cfg.max_blood] = point
  end
  point.pos = Vector3.New(cfg.t.x, cfg.t.y, cfg.t.z)
end

local VisibleRange = 60
local CreateCountPerFrame = 10

function ZombiePointManager:OnUpdate(x, y)
  local createList = self.createList
  local pointList = self.pointList
  for k, v in pairs(pointList) do
    if v and v.pos then
      local d = math.abs(y - v.pos.z)
      if d < VisibleRange then
        createList[v.guid] = v
        pointList[v.guid] = nil
      end
    end
  end
  pointList = self.blockGuidMap
  for k, v in pairs(pointList) do
    if v and v.pos then
      local d = math.abs(y - v.pos.z)
      if d < VisibleRange then
        createList[v.guid] = v
        pointList[v.guid] = nil
      end
    end
  end
  local count = 0
  for id, cfg in pairs(createList) do
    createList[id] = nil
    self:DoCreate(cfg)
    count = count + 1
    if count >= CreateCountPerFrame then
      return
    end
  end
end

function ZombiePointManager:DoCreate(cfg)
  self.battleMgr:CreateMonster(cfg.monsterId, cfg.pos, cfg)
end

return ZombiePointManager
