local this = class("collectionManager")
local _homeBuildingCollectionTpl = L_GameTpl:getHomeBuildingCollectionTpl()
local _homeCollectionWorldTpl = L_GameTpl:getHomeCollectionWorldTpl()
local _domainTpl = L_GameTpl:getDomainTpl()
local _productsCollectionTpl = L_GameTpl:getProductsCollectionTpl()
local COLLECTION_LIMIT = L_GameConstTpl:getValue("COLLECTION_LIMIT")
local COLLECTION_LATTICE_LIMIT = L_GameConstTpl:getValue("COLLECTION_LATTICE_LIMIT")
local BuildType = {
  Logging = 1,
  Quarry = 2,
  Mining = 3,
  Hunting = 4,
  ElementAltar = 5
}

function this:reqBuildCollect(guid, sourceBuild, callback)
  sourceBuild = sourceBuild or 0
  L_CollectionStore:req_CSProtoCollectBuildCreate(guid, sourceBuild, function(errCode)
    if errCode == L_Const.errorCode.ErrCodeSucc and callback then
      callback()
    end
  end)
end

function this:reqStartCollect(guid, planTime, callback)
  L_CollectionStore:req_CSProtoCollectStart(guid, planTime, function(errCode)
    if errCode == L_Const.errorCode.ErrCodeSucc and callback then
      callback()
    end
  end)
end

function this:reqCancelCollect(guid, callback)
  L_CollectionStore:req_CSProtoCollectStop(guid, function(errCode)
    if errCode == L_Const.errorCode.ErrCodeSucc then
      if callback then
        callback()
      end
    elseif errCode == L_Const.errorCode.ErrCodeHomeProductHasFinishCount then
      L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_homeProduction_03"))
    end
  end)
end

function this:reqCollectReward(guid, sourceBuild, callback)
  if type(guid) == "number" then
    guid = {guid}
  end
  if math.isEmpty(sourceBuild) then
    sourceBuild = nil
  end
  L_CollectionStore:req_CSProtoCollectGetReward(guid, sourceBuild, function(rspData, errCode)
    if errCode == L_Const.errorCode.ErrCodeSucc then
      local reward = rspData.rewards
      if not table.isEmpty(reward) then
        L_RewardManager:showPage(reward, rspData.src)
      end
      if callback then
        callback()
      end
    end
  end)
end

function this:reqCollectAllReward(guidList, sourceBuild, callback)
  if math.isEmpty(sourceBuild) then
    sourceBuild = nil
  end
  L_CollectionStore:req_CSProtoCollectGetReward(guidList, sourceBuild, function(rspData, errCode)
    if errCode == L_Const.errorCode.ErrCodeSucc then
      local reward = rspData.rewards
      if not table.isEmpty(reward) then
        L_RewardManager:showPage(reward, rspData.src)
      end
      if callback then
        callback()
      end
    end
  end)
end

function this:getIsCollectionMaxLevel(collectionId)
  local serverData = L_CollectionStore:getCollection(collectionId)
  local tpl_building = _homeBuildingCollectionTpl:getTplById(serverData.build_id)
  local level = _homeBuildingCollectionTpl:getLevel(tpl_building)
  local buildings = _homeBuildingCollectionTpl:getTplByCollectionId(collectionId)
  local maxLevel = table.count(buildings)
  return level >= maxLevel
end

function this:getCollectionNextLevelIsMaxLevel(collectionId)
  local serverData = L_CollectionStore:getCollection(collectionId)
  local tpl_building = _homeBuildingCollectionTpl:getTplById(serverData.build_id)
  local level = _homeBuildingCollectionTpl:getLevel(tpl_building)
  local buildings = _homeBuildingCollectionTpl:getTplByCollectionId(collectionId)
  local maxLevel = table.count(buildings)
  return maxLevel <= level + 1
end

function this:getCollectionObjByScene(sceneId)
  local res = self:getAllObjByScene(sceneId, 1)
  return res
end

function this:getWildBuffBuildObjByScene(sceneId)
  local res = self:getAllObjByScene(sceneId, 2)
  return res
end

function this:getAllObjByScene(sceneId, buildType)
  local allData = _homeCollectionWorldTpl.data
  local res = {}
  for i, tpl in pairs(allData) do
    local type = _homeCollectionWorldTpl:getType(tpl)
    if type == buildType then
      local domainId = _homeCollectionWorldTpl:getDomainId(tpl)
      local tpl_domain = _domainTpl:getTplById(domainId)
      local sceneId_tmp = _domainTpl:getSceneId(tpl_domain)
      if sceneId_tmp == sceneId then
        local collectionId = _homeCollectionWorldTpl:getId(tpl)
        table.insert(res, {
          objId = _homeCollectionWorldTpl:getWorldMapObjectUnfixed(tpl),
          collectId = collectionId
        })
      end
    end
  end
  return res
end

function this:getCollectCommonItemRewardList(collectionGuid, needSort)
  local serverData = L_CollectionStore:getCollection(collectionGuid)
  if table.isEmpty(serverData.items) then
    return {}
  end
  local res = {}
  for i, v in ipairs(serverData.items) do
    local canCollectCount = v.item_num
    if 0 < canCollectCount then
      local conf = L_ItemTplManager:getItemConfig(v.item_type, v.item_id)
      if canCollectCount <= COLLECTION_LATTICE_LIMIT then
        table.insert(res, {
          product_id = v.source_product_id,
          collect_num = canCollectCount,
          quality = conf.quality,
          type = v.item_type,
          itemId = v.item_id
        })
      else
        local remainCount = canCollectCount % COLLECTION_LATTICE_LIMIT
        local moreCell = canCollectCount // COLLECTION_LATTICE_LIMIT
        local cell = remainCount == 0 and moreCell or moreCell + 1
        for i = 1, cell do
          if i == cell then
            table.insert(res, {
              product_id = v.source_product_id,
              collect_num = remainCount,
              quality = conf.quality,
              type = v.item_type,
              itemId = v.item_id
            })
          else
            table.insert(res, {
              product_id = v.source_product_id,
              collect_num = COLLECTION_LATTICE_LIMIT,
              quality = conf.quality,
              type = v.item_type,
              itemId = v.item_id
            })
          end
        end
      end
    end
  end
  if needSort then
    table.sort(res, function(a, b)
      if a.quality == b.quality then
        return a.product_id > b.product_id
      else
        return a.quality > b.quality
      end
    end)
  end
  return res
end

function this:getCanCollectRewardList(collectionGuid, needSort)
  local serverData = L_CollectionStore:getCollection(collectionGuid)
  local tpl_building = _homeBuildingCollectionTpl:getTplById(serverData.build_id)
  local products = _homeBuildingCollectionTpl:getProducts(tpl_building)
  local res = {}
  for i, v in ipairs(products) do
    local canCollectCount = L_CollectionStore:getCollectionProductReward(collectionGuid, v).collect_num
    if 0 < canCollectCount then
      local productTpl = _productsCollectionTpl:getTplById(v)
      local reward = _productsCollectionTpl:getDropShow(productTpl)[1]
      local itemData = L_DataUtil.parseRewardConfigItem(reward)
      local conf = L_ItemTplManager:getItemConfig(itemData.itemType, itemData.itemId)
      if canCollectCount <= COLLECTION_LATTICE_LIMIT then
        table.insert(res, {
          product_id = v,
          collect_num = canCollectCount,
          quality = conf.quality
        })
      else
        local remainCount = canCollectCount % COLLECTION_LATTICE_LIMIT
        local moreCell = canCollectCount // COLLECTION_LATTICE_LIMIT
        local cell = remainCount == 0 and moreCell or moreCell + 1
        for i = 1, cell do
          if i == cell then
            table.insert(res, {
              product_id = v,
              collect_num = remainCount,
              quality = conf.quality
            })
          else
            table.insert(res, {
              product_id = v,
              collect_num = COLLECTION_LATTICE_LIMIT,
              quality = conf.quality
            })
          end
        end
      end
    end
  end
  if needSort then
    table.sort(res, function(a, b)
      if a.quality == b.quality then
        return a.product_id > b.product_id
      else
        return a.quality > b.quality
      end
    end)
  end
  return res
end

function this:judgeCanCollectReward()
  local all_serverData = L_CollectionStore:getAllCollection()
  local res = {}
  for collectionGuid, v in pairs(all_serverData) do
    if not table.isEmpty(v) and not math.isEmpty(v.build_id) then
      local tpl_building = _homeBuildingCollectionTpl:getTplById(v.build_id)
      local products = self:getCollectCommonItemRewardList(collectionGuid)
      for _, k in ipairs(products) do
        local canCollectCount = k.collect_num or 0
        if 0 < canCollectCount then
          table.insert(res, collectionGuid)
          break
        end
      end
    end
  end
  if table.isEmpty(res) then
    return false, nil
  end
  return true, res
end

function this:getStatus(collectionId)
  local collection = L_CollectionStore:getCollection(collectionId)
  if math.isEmpty(collection.build_id) then
    return L_MapConst.CollectionStatus.UnFixed
  end
  if math.isEmpty(collection.pet_guid) then
    return L_MapConst.CollectionStatus.NotSetPet
  else
    if L_SatietyStore:isWorkPause(collection.pet_guid) then
      return L_MapConst.CollectionStatus.Pause
    end
    local rewardList = self:getCollectCommonItemRewardList(collectionId)
    if #rewardList >= self:getMaxCollectionLimit() then
      return L_MapConst.CollectionStatus.Full
    end
  end
  return L_MapConst.CollectionStatus.Working
end

function this:getMaxCollectionLimit()
  return COLLECTION_LIMIT
end

function this:getSingleCollectCellLimit()
  return COLLECTION_LATTICE_LIMIT
end

function this:checkCanFixCollectionBuilding(guid)
  local _dropAudio = "Play_SFX_World_GPO_Build_Hunting"
  local buildings = _homeBuildingCollectionTpl:getTplByCollectionId(guid)
  local items = L_DataUtil.parseRewardConfig(_homeBuildingCollectionTpl:getMaterial(buildings[1]))
  local build_type = _homeBuildingCollectionTpl:getType(buildings[1])
  for i, v in pairs(items) do
    if L_ItemTplManager:getItemNum(v.itemType, v.itemId) < v.itemNum then
      L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("notice_shortageMaterial"))
      return false
    end
  end
  if build_type == BuildType.Logging then
    _dropAudio = "Play_SFX_World_GPO_Build_Logging"
  elseif build_type == BuildType.Quarry then
    _dropAudio = "Play_SFX_World_GPO_Build_Quarry"
  elseif build_type == BuildType.ElementAltar then
    _dropAudio = "Play_SFX_World_GPO_Build_ElementAltar"
  elseif build_type == BuildType.Hunting then
    _dropAudio = "Play_SFX_World_GPO_Build_Hunting"
  elseif build_type == BuildType.Mining then
    _dropAudio = "Play_SFX_World_GPO_Build_Mining"
  end
  L_AudioUtil.playSound(_dropAudio)
  return true
end

return this
