local this = {}
local _homeObjTpl = L_GameTpl:getHomeObjTpl()
local _homeBlockTpl = L_GameTpl:getHomeBlockTpl()
local _HomeBuildingTpl = L_GameTpl:getHomeBuildingTpl()
local _HomeBuildingGroupTpl = L_GameTpl:getHomeBuildingGroupTpl()
local _HomeBuildingProductionTpl = L_GameTpl:getHomeBuildingProductionTpl()
local _ProductsTpl = L_GameTpl:getProductsTpl()
local _PetSizeTpl = L_GameTpl:getPetHomeSizeTpl()
local _commonItemTpl = L_GameTpl:getCommonItemTpl()

function this.parseGridIdToPos(id)
  local x = id % L_Const.homeGridDataYOffset
  local y = id // L_Const.homeGridDataYOffset
  return C_Vector2(x * L_HomeStore.const_gridSize, y * L_HomeStore.const_gridSize)
end

function this.parsePosToGridId(x, y)
  local setX = x / L_HomeStore.const_gridSize
  local setY = y / L_HomeStore.const_gridSize
  setX = math.floor(setX)
  setY = math.floor(setY)
  return setX + L_Const.homeGridDataYOffset * setY
end

function this.parseGridData(itemId, anchorPos, dir)
  local tpl = _homeObjTpl:getTplById(itemId)
  local width = _homeObjTpl:getWidth(tpl)
  local height = _homeObjTpl:getHeight(tpl)
  local petSizeWidth, petSizeHeight, petPosX, petPosY, petRot = _homeObjTpl:getPetAreaInfo(tpl)
  local isVertical = dir % 2 == 1
  local gridData = {}
  gridData.anchorPos = anchorPos
  gridData.width = isVertical and height or width
  gridData.height = isVertical and width or height
  gridData.petSizeWidth = isVertical and petSizeHeight or petSizeWidth
  gridData.petSizeHeight = isVertical and petSizeWidth or petSizeHeight
  if dir == 0 then
    gridData.petPos = C_Vector2(petPosX, petPosY)
  elseif dir == 1 then
    gridData.petPos = C_Vector2(petPosY, width - petPosX - petSizeWidth)
  elseif dir == 2 then
    gridData.petPos = C_Vector2(width - petPosX - petSizeWidth, height - petPosY - petSizeHeight)
  elseif dir == 3 then
    gridData.petPos = C_Vector2(height - petPosY - petSizeHeight, petPosX)
  end
  gridData.petRot = petRot + dir * 90
  gridData.posIdList = {}
  for i = 0, gridData.width - 1 do
    for j = 0, gridData.height - 1 do
      local showX = anchorPos.x + i
      local showY = anchorPos.y + j
      if 0 <= showY and 0 <= showX then
        table.insert(gridData.posIdList, showX + showY * L_Const.homeGridDataYOffset)
      else
        table.insert(gridData.posIdList, -1)
      end
    end
  end
  return gridData
end

function this.getFrontInfos(lookingId, dir, dirLength, dirWidth, block)
  local minPos = L_HomeUtil.parseGridIdToPos(lookingId)
  if dir.z ~= 0 then
    if dir.z == -1 then
      minPos = minPos - C_Vector2(math.ceil(dirWidth / 2) - 1, math.ceil((dirLength - 1) / 2))
    else
      minPos = minPos - C_Vector2(math.ceil(dirWidth / 2) - 1, math.floor((dirLength - 1) / 2))
    end
  elseif dir.x == -1 then
    minPos = minPos - C_Vector2(math.ceil((dirLength - 1) / 2), math.ceil(dirWidth / 2) - 1)
  else
    minPos = minPos - C_Vector2(math.floor((dirLength - 1) / 2), math.ceil(dirWidth / 2) - 1)
  end
  local lookingIds = {}
  local minId, maxId = math.huge, -math.huge
  for i = 0, (dir.z ~= 0 and dirWidth or dirLength) - 1 do
    for j = 0, (dir.z ~= 0 and dirLength or dirWidth) - 1 do
      local gridId = L_HomeUtil.parsePosToGridId(minPos.x + i, minPos.y + j)
      if block and block.cropPart and block.cropPart:getIsCropAreaById(gridId) then
        minId = math.min(minId, gridId)
        maxId = math.max(maxId, gridId)
        table.insert(lookingIds, gridId)
      end
    end
  end
  local minPos, maxPos = L_HomeUtil.parseGridIdToPos(minId), L_HomeUtil.parseGridIdToPos(maxId)
  return minId, lookingIds, (minPos + maxPos) / 2 + C_Vector2(0.5, 0.5), maxPos.x - minPos.x + 1, maxPos.y - minPos.y + 1
end

function this.resetGameObjectActive(go)
  go:SetActive(false)
  go:SetActive(true)
end

function this.getBarrierGridMap(centerPos, euler, sizeX, sizeY)
  local expandSizeX, expandSizeY = this.getAABBExpandSize(euler.y, sizeX, sizeY)
  local cornor1, cornor2, cornor3, cornor4 = this.getRectCornors(centerPos, C_Quaternion.Euler(euler), sizeX, sizeY)
  local res = {}
  for x = math.floor(centerPos.x - expandSizeX / 2), math.floor(centerPos.x + expandSizeX / 2) do
    local min, max = this.getRectMinMaxY(x, x + 1, cornor1, cornor2, cornor3, cornor4)
    if min and max then
      for y = math.floor(min), math.floor(max) do
        res[L_HomeUtil.parsePosToGridId(x, y)] = true
      end
    end
  end
  return res
end

function this.getAABBExpandSize(rotation, sizeX, sizeY)
  local sin = math.abs(math.sin(math.rad(rotation)))
  local cos = math.abs(math.cos(math.rad(rotation)))
  local resX = sizeX * cos + sizeY * sin
  local resY = sizeX * sin + sizeY * cos
  return resX, resY
end

function this.getRectCornors(centerPos, rotation, sizeX, sizeY)
  local cornor1 = centerPos + rotation * C_Vector3(sizeX / 2, 0, sizeY / 2)
  local cornor2 = centerPos + rotation * C_Vector3(sizeX / 2, 0, -sizeY / 2)
  local cornor3 = centerPos + rotation * C_Vector3(-sizeX / 2, 0, -sizeY / 2)
  local cornor4 = centerPos + rotation * C_Vector3(-sizeX / 2, 0, sizeY / 2)
  return C_Vector2(cornor1.x, cornor1.z), C_Vector2(cornor2.x, cornor2.z), C_Vector2(cornor3.x, cornor3.z), C_Vector2(cornor4.x, cornor4.z)
end

function this.getRectMinMaxY(xMin, xMax, p1, p2, p3, p4)
  local min1, max1 = this.getLineSegMinMaxY(xMin, xMax, p1, p2)
  local min2, max2 = this.getLineSegMinMaxY(xMin, xMax, p2, p3)
  local min3, max3 = this.getLineSegMinMaxY(xMin, xMax, p3, p4)
  local min4, max4 = this.getLineSegMinMaxY(xMin, xMax, p4, p1)
  if not min1 and not min2 and not min3 and not min4 then
    return
  end
  local min = math.min(min1 or L_Const.maxInt, min2 or L_Const.maxInt, min3 or L_Const.maxInt, min4 or L_Const.maxInt)
  local max = math.max(max1 or L_Const.minInt, max2 or L_Const.minInt, max3 or L_Const.minInt, max4 or L_Const.minInt)
  return min, max
end

function this.getLineSegMinMaxY(xMin, xMax, point1, point2)
  if point1.x > point2.x then
    point1, point2 = point2, point1
  end
  if xMax <= point1.x or xMin >= point2.x then
    return
  end
  xMin = math.max(point1.x, xMin)
  xMax = math.min(point2.x, xMax)
  if point2.x == point1.x then
    return math.min(point1.y, point2.y), math.max(point1.y, point2.y)
  end
  local k = (point2.y - point1.y) / (point2.x - point1.x)
  local yMin = (xMin - point1.x) * k + point1.y
  local yMax = (xMax - point1.x) * k + point1.y
  return yMin, yMax
end

this.indexDelta = {
  [1] = {x = -1, y = -1},
  [2] = {x = 0, y = -1},
  [3] = {x = 1, y = -1},
  [4] = {x = -1, y = 0},
  [6] = {x = 1, y = 0},
  [7] = {x = -1, y = 1},
  [8] = {x = 0, y = 1},
  [9] = {x = 1, y = 1}
}

function this.getCropNearByOpenInfo(blockId, id)
  local data = L_HomeCropStore:getFieldData(blockId, id)
  if data and data.status ~= L_Const.WorldMapFieldStatusType.WMFST_CLOSE then
    return {}
  end
  local nearBy = L_HomeUtil.getNearbyCropIds(id)
  local checkMap = {}
  local tempResMap = {}
  for k, v in pairs(this.indexDelta) do
    checkMap[k] = k % 2 == 1 or nil
  end
  local edgeCount = 0
  for k, v in pairs(nearBy) do
    if k % 2 == 0 then
      local data = L_HomeCropStore:getFieldData(blockId, v.id)
      if data and data.status ~= L_Const.WorldMapFieldStatusType.WMFST_CLOSE then
        tempResMap[k] = true
        local c1, c2 = L_HomeUtil.getCornersByEdge(k)
        checkMap[c1] = nil
        checkMap[c2] = nil
        edgeCount = edgeCount + 1
      end
    end
  end
  for k, v in pairs(checkMap) do
    local data = L_HomeCropStore:getFieldData(blockId, nearBy[k].id)
    tempResMap[k] = data and data.status ~= L_Const.WorldMapFieldStatusType.WMFST_CLOSE or nil
  end
  local resMap = {}
  if edgeCount <= 1 then
    for k, v in pairs(tempResMap) do
      if k % 2 == 0 then
        resMap[k] = L_Const.homeCropEdgeType.I
      else
        resMap[k] = L_Const.homeCropEdgeType.C
      end
    end
  elseif edgeCount == 2 then
    for k, v in pairs(tempResMap) do
      if k % 2 == 0 then
        local opposite = L_HomeUtil.getOpposite(k)
        if tempResMap[opposite] then
          for kk, vv in pairs(tempResMap) do
            if kk % 2 == 0 then
              resMap[kk] = L_Const.homeCropEdgeType.I
            else
              resMap[kk] = L_Const.homeCropEdgeType.C
            end
          end
          break
        else
          local c2
          for kk, vv in pairs(tempResMap) do
            if kk ~= k and kk % 2 == 0 then
              c2 = kk
              break
            end
          end
          local included = L_HomeUtil.getIncludedCorner(k, c2)
          resMap[included] = L_Const.homeCropEdgeType.L
          for kk, vv in pairs(tempResMap) do
            if kk % 2 == 1 then
              resMap[kk] = L_Const.homeCropEdgeType.C
            end
          end
          break
        end
      end
    end
  elseif edgeCount == 3 then
    for i = 2, 8, 2 do
      if not tempResMap[i] then
        resMap[L_HomeUtil.getOpposite(i)] = L_Const.homeCropEdgeType.U
        break
      end
    end
  elseif edgeCount == 4 then
    resMap[2] = L_Const.homeCropEdgeType.O
  end
  return resMap
end

local getNearbyCropIds_result = {}

function this.getNearbyCropIds(id)
  if not getNearbyCropIds_result[id] then
    local pos = L_HomeUtil.parseGridIdToPos(id)
    local res = {}
    local x, y
    for k, v in pairs(this.indexDelta) do
      x, y = pos.x + v.x, pos.y + v.y
      res[k] = {
        x = x,
        y = y,
        id = L_HomeUtil.parsePosToGridId(x, y)
      }
    end
    getNearbyCropIds_result[id] = res
  end
  return getNearbyCropIds_result[id]
end

function this.getOpposite(index)
  return 10 - index
end

function this.getIncludedCorner(index1, index2)
  local min = math.min(index1, index2)
  local max = math.max(index1, index2)
  if min == 2 then
    return max - 3
  elseif max == 8 then
    return min + 3
  end
end

function this.getCornersByEdge(index)
  if index == 4 then
    return 1, 7
  elseif index == 6 then
    return 3, 9
  elseif index == 2 or index == 8 then
    return index - 1, index + 1
  end
end

function this.getIndexYaw(index)
  if index == 3 or index == 6 then
    return 270
  elseif index == 8 or index == 9 then
    return 180
  elseif index == 4 or index == 7 then
    return 90
  end
  return 0
end

function this.getIdsCanPlant(blockId, ids)
  for k, v in pairs(ids) do
    local data = L_HomeCropStore:getFieldData(blockId, v)
    if not data or data.status ~= L_Const.WorldMapFieldStatusType.WMFST_OPEN then
      return false
    end
  end
  return true
end

function this.checkStartBuildingGuide(buildingId)
  local _buildingTpl = L_GameTpl:getHomeBuildingTpl()
  local _buildingGroupTpl = L_GameTpl:getHomeBuildingGroupTpl()
  local tpl = _buildingTpl:getTplById(buildingId)
  local groupTpl = _buildingGroupTpl:getTplById(_buildingTpl:getGroupId(tpl))
  local buildType = _buildingGroupTpl:getType(groupTpl)
  if buildType == L_Const.WorldMapBuildType.WMBT_PRODUCT then
    L_GuideManager:startGuide(L_Const.guideId.product)
  elseif buildType == L_Const.WorldMapBuildType.WMBT_HOUSE then
    L_GuideManager:startGuide(L_Const.guideId.house)
  end
end

function this.getFormalDir(dir)
  local leastAngle = math.huge
  local result
  for k, v in ipairs(L_HomeConst.operateDir) do
    local angle = C_Vector3.Angle(dir, v)
    if leastAngle > angle then
      leastAngle = angle
      result = v
    end
  end
  return result
end

function this.getNextDir(dir)
  if dir == C_Vector3.forward then
    return C_Vector3.right
  end
  if dir == C_Vector3.right then
    return C_Vector3.back
  end
  if dir == C_Vector3.back then
    return C_Vector3.left
  end
  if dir == C_Vector3.left then
    return C_Vector3.forward
  end
end

function this.getPetSortList()
  local allPets = L_PetStore:getPetList()
  local tmp = {}
  for i, v in pairs(allPets) do
    table.insert(tmp, v.guid)
  end
  table.sort(tmp, function(a, b)
    local aInfo = L_PetStore:getPetItem(a)
    local bInfo = L_PetStore:getPetItem(b)
    local isWorkingA = aInfo:isWorking() and 1 or 0
    local isWorkingB = bInfo:isWorking() and 1 or 0
    if isWorkingA == isWorkingB then
      local levelA = aInfo.lv
      local levelB = bInfo.lv
      if levelA == levelB then
        return aInfo.guid < bInfo.guid
      else
        return levelA > levelB
      end
    else
      return isWorkingA < isWorkingB
    end
  end)
  return tmp
end

function this.getIsBlockUnlock(blockId)
  if math.isEmpty(blockId) then
    return true
  end
  local tpl = _homeBlockTpl:getTplById(blockId)
  return L_ConditionManager:singleIsComplete(_homeBlockTpl:getUnlockCondi(tpl))
end

function this.getBlockLockTipDesc(blockId)
  local tpl = _homeBlockTpl:getTplById(blockId)
  return L_ConditionManager:getTipDesc({
    _homeBlockTpl:getUnlockCondi(tpl)
  })
end

function this.checkPetSatiety(petGuid)
  if math.isEmpty(petGuid) then
    return true
  end
  return not L_SatietyStore:isWorkPause(petGuid)
end

function this.isInHome()
  local curModule = L_WorldManager:getCurModule()
  return curModule == L_Const.worldModule.home
end

function this.switchInOutHome()
  local curModule = L_WorldManager:getCurModule()
  if curModule == L_Const.worldModule.home then
    if L_WorldManager:getIsActive() then
      local data = {
        txtContent = L_WordsTpl:getValue("notice_home_transfer_out"),
        confirmCallback = function()
          L_HomeStore:req_exitHome()
        end
      }
      L_GameUtil.showCommonTip(data)
    end
    return
  end
  L_SystemBreakManager:jumpTo(L_SystemConst.enum.home)
end

function this.getBuildingType(guid)
  local buildingData = L_HomeStore:getHomeBuildingByGuid(guid)
  local buildingTpl = _HomeBuildingTpl:getTplById(buildingData.build_id)
  local groupTpl = _HomeBuildingGroupTpl:getTplById(_HomeBuildingTpl:getGroupId(buildingTpl))
  return _HomeBuildingGroupTpl:getType(groupTpl)
end

function this.getProductBuildingSizeDesc(buildingId)
  local productTpl = _HomeBuildingProductionTpl:getTplById(buildingId)
  local petSize = _HomeBuildingProductionTpl:getPetSize(productTpl)
  local txt = ""
  for i, v in ipairs(petSize) do
    local tpl_size = _PetSizeTpl:getTplById(v)
    txt = string.concat(txt, _PetSizeTpl:getSizeName(tpl_size))
    if i < #petSize then
      txt = string.concat(txt, "/")
    end
  end
  return txt
end

function this.checkBuildCanProduct(guid, productId)
  if guid == nil or guid <= 0 or productId == nil or productId <= 0 then
    return false
  end
  local serverData = L_HomeStore:getHomeBuildingByGuid(guid)
  if serverData == nil then
    return false
  end
  local tpl_building = _HomeBuildingTpl:getTplById(serverData.build_id)
  local level = _HomeBuildingTpl:getLevel(tpl_building)
  local productTpl = _ProductsTpl:getTplById(productId)
  if level < _ProductsTpl:unlockBuildingLevel(productTpl) then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_product_resolution_lock"))
    return false
  end
  if not L_ProductManager:checkProduceQueueAvaliable(guid) then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_product_lack_produce_queue"))
    return false
  end
  local isNeedPet = _ProductsTpl:getIsNeedPet(productTpl)
  if isNeedPet and not L_ProductManager:isBuildingHasPet(guid) then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_product_need_pet"))
    return
  end
  local rewardInfo = _ProductsTpl:getRewardId(productTpl)[1]
  if rewardInfo then
    local rewardItemType = rewardInfo[1]
    local rewardItemId = rewardInfo[2]
    if rewardItemType == L_Const.resType.mountSaddle then
      local isHas = AzurWorld.mountMgr:GetIdMountSaddleUnlock(rewardItemId) == true
      if isHas then
        L_FlyMsgManager:showNormalMsg(L_Lang:get(L_WordsTpl:getValue("notice_home_product_reachlimit")))
        return false
      end
      local isInProduction = false
      local queueData = L_ProductManager:getProduceQueueForBuilding(guid)
      for _, queueItemData in pairs(queueData) do
        if queueItemData.isEmpty == false and queueItemData.product and queueItemData.product.product_id then
          local productsTpl = _ProductsTpl:getTplById(queueItemData.product.product_id)
          local rewardItemIdInQueue = _ProductsTpl:getRewardId(productsTpl)[1][2]
          if rewardItemIdInQueue == rewardItemId then
            isInProduction = true
          end
        end
      end
      if isInProduction then
        L_FlyMsgManager:showNormalMsg(L_Lang:get(L_WordsTpl:getValue("notice_home_product_willreachlimit")))
        return false
      end
    end
  end
  local count, limitCnt = L_ProductManager:getLimitForBuildingItem(productId)
  if limitCnt ~= nil and limitCnt <= count then
    L_FlyMsgManager:showNormalMsg(L_WordsTpl:getValue("ui_home_building_reach_limit"))
    return false
  end
  return true
end

function this:getPlayerInBlock()
  if L_HomeConst.useCS then
    local blockId, gridId = AzurWorld.HomeMgr:GetInteractBlockIdAndGridIdWithPlayerByOffset()
    return blockId, gridId
  end
  local blockIndex, pos, dir = L_HomeManager:getPlayerFaceGrid(0)
  return blockIndex or 0, pos and L_HomeUtil.parsePosToGridId(pos.x, pos.y) or 0
end

function this.focusBuild(guid, focusType)
  L_EntityManager:showOrHideRoot(L_Const.WorldNode.PLAYER, math.isEmpty(guid))
  L_EntityManager:showOrHideRoot(L_Const.WorldNode.PLAYERPETNODE, math.isEmpty(guid))
  local cameraController
  if focusType ~= L_HomeConst.FocusType.NONE then
    if math.isEmpty(guid) then
      local blend = L_CameraManager:getBlendStyle(L_Const.blendStyleMode.custom)
      blend.time = 1000
      L_CameraManager:revertCamController(blend)
    else
      cameraController = L_CameraManager:switchToHomeBuild()
    end
  end
  local manager = AzurWorld.HomeMgr
  local dis, focusTrans, centerTrans = manager:LookAtBuild(guid)
  if cameraController then
    if focusType == L_HomeConst.FocusType.UPGRADE then
      cameraController:setData(focusTrans, dis)
    else
      cameraController:setData(centerTrans, 2)
    end
  end
end

function this.focusBuildWithCustomHideList(guid, focusType, hideNodeList, hideSourceKey)
  if focusType == L_HomeConst.FocusType.NONE then
    return
  end
  this.showOrHideEntityNodeWithCustomNodeList(false, hideNodeList, hideSourceKey)
  local cameraController = L_CameraManager:switchToHomeBuild()
  local manager = AzurWorld.HomeMgr
  local dis, focusTrans, centerTrans, mainUIFocusTrans = manager:LookAtBuilding(guid)
  if focusType == L_HomeConst.FocusType.UPGRADE then
    cameraController:setData(focusTrans, dis)
  elseif focusType == L_HomeConst.FocusType.MAINUI then
    dis = L_Vector3.getRot(mainUIFocusTrans).z
    cameraController:setData(mainUIFocusTrans, dis)
  elseif focusType == L_HomeConst.FocusType.CENTER then
    cameraController:setData(centerTrans, 2)
  end
end

function this.exitFocusBuildAndRevertCustomHideNodeList(hideNodeList, hideSourceKey)
  local manager = AzurWorld.HomeMgr
  manager:ExitLookAtBuilding()
  local blend = L_CameraManager:getBlendStyle(L_Const.blendStyleMode.cut)
  L_CameraManager:revertCamController(blend)
  this.showOrHideEntityNodeWithCustomNodeList(true, hideNodeList, hideSourceKey)
end

function this.showOrHideEntityNodeWithCustomNodeList(isShow, nodeList, hideSourceKey)
  this.hideNodeDic = this.hideNodeDic or {}
  for _, node in pairs(nodeList) do
    this.hideNodeDic[node] = this.hideNodeDic[node] or {
      hideSourceKeySet = {},
      active = true
    }
    local hideNodeState = this.hideNodeDic[node]
    local getHideSourceSetLength = function(hideSourceKeySet)
      local length = 0
      for _, _ in pairs(hideSourceKeySet) do
        length = length + 1
      end
      return length
    end
    if isShow == true then
      hideNodeState.hideSourceKeySet[hideSourceKey] = nil
      if getHideSourceSetLength(hideNodeState.hideSourceKeySet) == 0 and hideNodeState.active == false then
        this.showOrHideEntityNode(true, node)
        hideNodeState.active = true
      end
    elseif isShow == false then
      hideNodeState.hideSourceKeySet[hideSourceKey] = true
      if getHideSourceSetLength(hideNodeState.hideSourceKeySet) > 0 and hideNodeState.active == true then
        this.showOrHideEntityNode(false, node)
        hideNodeState.active = false
      end
    end
  end
end

function this.showOrHideEntityNode(isShow, node)
  if node == L_HomeConst.HideNodeOfHomePet then
    AzurWorld.HomeMgr:SetAllPetHide(not isShow, "LHomeUtil")
  else
    L_EntityManager:showOrHideRoot(node, isShow)
  end
end

function this.focusBlock(guid)
  if math.isEmpty(guid) then
    local blend = L_CameraManager:getBlendStyle(L_Const.blendStyleMode.custom)
    blend.time = 1000
    L_CameraManager:revertCamController(blend)
  else
    local cameraController = L_CameraManager:switchToHomeBuild()
    local manager = AzurWorld.HomeMgr
    local dis, focusTrans = manager:LookAtBlock(guid)
    cameraController:setData(focusTrans, dis)
  end
end

function this.getBuildEntity(guid)
  if L_HomeConst.useCS then
    local manager = AzurWorld.HomeMgr
    return manager:GetHomeBuild(guid)
  else
    return L_HomeManager:getBuildingEntityByGuid(guid)
  end
end

function this.checkConditionItems(cond, items)
  local isSatisfy, conditionRess = L_ConditionManager:isComplete(cond)
  if not isSatisfy then
    return false
  end
  for _, item in ipairs(items) do
    if L_ItemTplManager:getItemNum(item.itemType, item.itemId) < item.itemNum then
      return false
    end
  end
  return true
end

function this.canBuildUpgrade(guid)
  local _homeBuildingTpl = L_GameTpl:getHomeBuildingTpl()
  local serverData = L_HomeStore:getHomeBuildingByGuid(guid)
  if not serverData then
    return false
  end
  local buildingId = serverData.build_id
  local tpl = _homeBuildingTpl:getTplById(buildingId)
  local nextId = _homeBuildingTpl:getNextLevel(tpl)
  if math.isEmpty(nextId) then
    return false
  end
  local nextTpl = _homeBuildingTpl:getTplById(nextId)
  local upgradeCondition = _homeBuildingTpl:getUpgradeCondition(nextTpl)
  local items = L_DataUtil.parseRewardConfig(_homeBuildingTpl:getMaterial(nextTpl))
  return this.checkConditionItems(upgradeCondition, items)
end

function this.canCollectUpgrade(id)
  local homeBuildingCollectionTpl = L_GameTpl:getHomeBuildingCollectionTpl()
  local serverData = L_CollectionStore:getCollection(id)
  local buildingId = serverData.build_id
  local tpl = homeBuildingCollectionTpl:getTplById(buildingId)
  local level = homeBuildingCollectionTpl:getLevel(tpl)
  local buildings = homeBuildingCollectionTpl:getTplByCollectionId(id)
  local nextTpl = buildings[level + 1]
  if not nextTpl then
    return false
  end
  local upgradeCondition = homeBuildingCollectionTpl:getUpgradeCondition(nextTpl)
  local items = L_DataUtil.parseRewardConfig(homeBuildingCollectionTpl:getMaterial(nextTpl))
  return this.checkConditionItems(upgradeCondition, items)
end

function this.canRanchUpgrade(blockId)
  local _HomeRanchTpl = L_GameTpl:getHomeRanchTpl()
  local ranchData = L_HomeRanchStore:getBlockRanchData(blockId)
  local currLv = ranchData and ranchData.lv or 1
  local nextTpl = _HomeRanchTpl:getTplById(currLv + 1)
  if not nextTpl then
    return false
  end
  local upgradeCondition = _HomeRanchTpl:getUpgradeCondition(nextTpl)
  local items = L_DataUtil.parseRewardConfig(_HomeRanchTpl:getCost(nextTpl))
  return this.checkConditionItems(upgradeCondition, items)
end

function this.getHomeBuildingProductionInfo(buildingGuid, productGuid)
  local product = L_ProductManager:getProductByGuid(buildingGuid, productGuid)
  local iconPath, onceTime, img_iconFilter
  if L_HomeUtil.getBuildingType(buildingGuid) == L_Const.WorldMapBuildType.WMBT_HATCH then
    local special = L_ProductManager:getProductSpecialParams(buildingGuid, productGuid)
    local petEggData = L_PetStore:getPetEggItem(special.extra_guid)
    local petEggConf = L_ItemTplManager:getPetEggItem(petEggData.configId, special.extra_guid)
    iconPath = petEggConf.icon
    onceTime = L_PetStore:getEggIncubationTime(L_PetStore:getPetEggItem(special.extra_guid).configId, buildingGuid)
  else
    onceTime = L_ProductManager:getProduceOnceTime(buildingGuid, product.product_id)
    local itemData = L_ProductManager:getProductRewardItemData(product.product_id)
    local item = L_ItemTplManager:getItemConfig(itemData.itemType, itemData.itemId)
    local commonItemTpl = L_GameTpl:getCommonItemTpl():getTplById(itemData.itemId)
    img_iconFilter = commonItemTpl and L_GameTpl:getCommonItemTpl():getFilterIcon(commonItemTpl) or ""
    iconPath = item.icon
  end
  return {
    iconPath = iconPath,
    onceTime = onceTime,
    img_iconFilter = img_iconFilter
  }
end

return this
