local GiftSystemManager = BaseClass("GiftSystemManager")
require("DataCenter.GiftSystem.GiftSystemConst")
local Localization = CS.GameEntry.Localization
IsGiftSystemOpen = true
local MinGiftLevel = 0
local CAN_PLAY_EFFECT_KEY = "CAN_PLAY_EFFECT_KEY"
local GIFT_EFFECT_HISTORY_LIST = "GIFT_EFFECT_HISTORY_LIST"
local __init = function(self)
  self:AddListener()
  self.receivingList = {}
  self.privilegeTemplateList = nil
  self.expList = {}
  self.claimedPrivileges = {}
  self.giftLevel = MinGiftLevel
  self.giftExp = 0
  self.giftGoods = nil
  self.idMap = nil
  self.maxLevel = nil
  self.animQueen = {}
  self.animHistory = {}
  self.canPlayEffect = true
  self.lastSendTime = -1
end
local __delete = function(self)
  self.receivingList = {}
  self.privilegeTemplateList = nil
  self.expList = {}
  self.claimedPrivileges = {}
  self.giftLevel = MinGiftLevel
  self.giftExp = 0
  self.giftGoods = nil
  self.idMap = nil
  self.maxLevel = nil
  self.animQueen = {}
  self.animHistory = {}
  self.canPlayEffect = true
  self.lastSendTime = -1
  self:RemoveListener()
end
local AddListener = function(self)
  function self.OnUpdateGiftSystemOpen()
    self:UpdateGiftSystemOpen()
  end
  
  EventManager:GetInstance():AddListener(EventId.MainLvUp, self.OnUpdateGiftSystemOpen)
end
local RemoveListener = function(self)
  EventManager:GetInstance():RemoveListener(EventId.MainLvUp, self.OnUpdateGiftSystemOpen)
end
local InitData = function(self, t)
  self:InitAnim()
  local giftObj = t.giftObj or {}
  self.giftLevel = giftObj.level or MinGiftLevel
  self.giftExp = giftObj.exp or 0
  if not string.IsNullOrEmpty(giftObj.privilegeReward) then
    local list = string.split(giftObj.privilegeReward, "|")
    for _, v in pairs(list) do
      self.claimedPrivileges[tonumber(v)] = true
    end
  end
  self:UpdateGiftSystemOpen()
end

function GiftSystemManager:UpdateGiftSystemOpen()
  self.minSendGiftLevel = LuaEntry.DataConfig:TryGetNum("gift_giving", "k1", 10)
  local openServer = LuaEntry.DataConfig:TryGetStr("gift_giving", "k3", "")
  if string.IsNullOrEmpty(openServer) then
    IsGiftSystemOpen = true
  else
    local serverIds = string.split(openServer, "-")
    IsGiftSystemOpen = CommonUtil.IsGrayServer(tonumber(serverIds[1]), tonumber(serverIds[2]))
  end
  IsGiftSystemOpen = IsGiftSystemOpen and (not (LuaEntry.Player.level < self.minSendGiftLevel) or not (DataCenter.BuildManager.MainLv < self.minSendGiftLevel))
end

function GiftSystemManager:GetGiftShopSellDict()
  local showDataList = DataCenter.CommonShopManager:GetGoodsListByShopType(CommonShopType.GiftShop)
  local sellDict = {}
  for _, data in ipairs(showDataList) do
    local goodsId = data.itemId
    local goods = self:GetGiftGoods(goodsId)
    if goods then
      local isShow = false
      local expired = self:IsGiftExpired(goodsId)
      local show = self:GetShowConditions(goods)
      if goods.show == 1 and not expired and show then
        local isActivityOpening = false
        if not string.IsNullOrEmpty(goods.activity_id) then
          local isOpen = DataCenter.ActivityListDataManager:CheckIfActivityOpen(nil, goods.activity_id) or false
          if isOpen then
            isActivityOpening = true
          end
        end
        if isActivityOpening == true or string.IsNullOrEmpty(goods.activity_id) then
          isShow = true
        end
        if isShow then
          sellDict[goodsId] = true
        end
      end
    end
  end
  return sellDict
end

function GiftSystemManager:GetGiftList(windowType)
  local list
  local isSend = windowType == GiftSystemConst.WindowType.Send
  if isSend then
    list = DataCenter.ItemTemplateManager:GetTypeListByType(161)
  else
    list = DataCenter.ItemTemplateManager:GetTypeListByType(162)
  end
  local result = {}
  local showDataList = DataCenter.CommonShopManager:GetGoodsListByShopType(CommonShopType.GiftShop)
  for _, v in pairs(list) do
    local goods = self:GetGiftGoods(v.id)
    local num = self:GetGiftNum(v.id)
    if goods then
      local isShow = false
      if isSend then
        local expired = self:IsGiftExpired(v.id)
        if 0 < num then
          isShow = not expired
        else
          local show = self:GetShowConditions(goods)
          if goods.show == 1 and not expired then
            local isActivityOpening = false
            if not string.IsNullOrEmpty(goods.activity_id) then
              local isOpen = DataCenter.ActivityListDataManager:CheckIfActivityOpen(nil, goods.activity_id) or false
              if isOpen then
                isActivityOpening = true
              end
            end
            if isActivityOpening == true or string.IsNullOrEmpty(goods.activity_id) then
              if goods.pay == 0 then
                isShow = show
              else
                for _, data in ipairs(showDataList) do
                  if tostring(data.itemId) == tostring(goods.id) then
                    isShow = show
                    break
                  end
                end
              end
            end
          end
        end
      else
        isShow = 0 < num
      end
      if isShow then
        table.insert(result, v)
      end
    end
  end
  table.sort(result, function(a, b)
    local numA = self:GetGiftNum(a.id)
    local numB = self:GetGiftNum(b.id)
    if numA == 0 ~= (numB == 0) then
      return numA ~= 0 and numB == 0
    end
    local goodsA = self:GetGiftGoods(a.id)
    local goodsB = self:GetGiftGoods(b.id)
    if goodsA.add_exp ~= goodsB.add_exp then
      return goodsA.add_exp > goodsB.add_exp
    end
    return tonumber(a.id) < tonumber(b.id)
  end)
  return result
end

function GiftSystemManager:GetGiftGoods(id)
  local list = self:GetGiftGoodsList()
  local goods = list and list[tonumber(id)]
  if goods == nil then
    local originId = self:GetOriginId(id)
    goods = list and list[tonumber(originId)]
  end
  return goods
end

function GiftSystemManager:GetShowConditions(goods)
  local eaShow = goods.ea == 1 and CommonUtil.IsGrayServer(3, 68) or goods.ea == 0
  local serverShow = true
  if 0 < goods.show_condition_server then
    serverShow = tonumber(LuaEntry.Player.serverId) > goods.show_condition_server
  end
  local condShow = true
  if 0 < #goods.show_condition then
    local condType = tonumber(goods.show_condition[1])
    if condType == 1 then
      local param = tonumber(goods.show_condition[2]) or 0
      local season = SeasonUtil.GetSeason()
      condShow = param <= season
    elseif condType == 2 then
      local param = tonumber(goods.show_condition[2]) or 0
      local day = UITimeManager:GetInstance():GetOpenServerDay()
      condShow = param <= day
    elseif condType == 3 then
      local param2 = tonumber(goods.show_condition[2]) or 0
      condShow = param2 <= SeasonUtil.GetSeasonDay()
    elseif condType == 4 then
      local param2 = tonumber(goods.show_condition[2]) or 0
      local param3 = tonumber(goods.show_condition[3]) or 0
      local season = SeasonUtil.GetSeason()
      condShow = param2 < season or season == param2 and param3 <= SeasonUtil.GetSeasonDay()
    elseif condType == 5 then
      local param2 = tonumber(goods.show_condition[2]) or 0
      local param3 = tonumber(goods.show_condition[3]) or 0
      local param4 = tonumber(goods.show_condition[4]) or 0
      local param5 = tonumber(goods.show_condition[5]) or 0
      local season = SeasonUtil.GetSeason()
      local day = SeasonUtil.GetSeasonDay()
      local cond1 = param2 < season or season == param2 and param3 <= day
      local cond2 = param4 > season or season == param4 and param5 > day
      condShow = cond1 and cond2
    end
  end
  return eaShow and serverShow and condShow
end

function GiftSystemManager:GetGiftGoodsList()
  if self.giftGoods then
    return self.giftGoods
  end
  self.giftGoods = {}
  LocalController:instance():visitTable(TableName.LW_GIFT_GOODS, function(id, lineData)
    local rowData = {}
    rowData.id = lineData.id
    rowData.cross = lineData.cross
    rowData.add_exp = lineData.add_exp
    rowData.ep_gift = lineData.ep_gift
    rowData.convert_item = lineData.convert_item
    rowData.pay = lineData.pay
    rowData.icon_small = lineData.icon_small
    rowData.icon_mid = lineData.icon_mid
    rowData.icon_big = lineData.icon_big
    rowData.show = lineData.show
    rowData.activity_id = lineData.activity_id
    rowData.ea = lineData.ea or 0
    rowData.effect_id = lineData.effect_id
    rowData.sound_id = lineData.sound_id
    rowData.model = lineData.model
    rowData.group_id = not string.IsNullOrEmpty(lineData.group_id) and string.split(lineData.group_id, "|") or {}
    rowData.group_icon = not string.IsNullOrEmpty(lineData.group_icon) and string.split(lineData.group_icon, "|") or {}
    rowData.group_sound = not string.IsNullOrEmpty(lineData.group_sound) and string.split(lineData.group_sound, "|") or {}
    rowData.group_effect = not string.IsNullOrEmpty(lineData.group_effect) and string.split(lineData.group_effect, "|") or {}
    rowData.group_pic = not string.IsNullOrEmpty(lineData.group_pic) and string.split(lineData.group_pic, "|") or {}
    rowData.group_model = not string.IsNullOrEmpty(lineData.group_model) and string.split(lineData.group_model, "|") or {}
    rowData.num_send_country = toInt(lineData.num_send_country)
    rowData.show_condition = not string.IsNullOrEmpty(lineData.show_condition) and string.split(lineData.show_condition, "|") or {}
    rowData.show_condition_server = toInt(lineData.show_condition_server)
    self.giftGoods[lineData.id] = rowData
  end)
  return self.giftGoods
end

function GiftSystemManager:GetGiftNum(id)
  if DataCenter.ItemTemplateManager:GetItemTemplate(id) ~= nil then
    local item = DataCenter.ItemData:GetItemById(id)
    if item ~= nil then
      return item.count or 0
    end
  end
  return 0
end

function GiftSystemManager:GetGiftPrivilegeList()
  self.privilegeList = {}
  table.insert(self.privilegeList, {
    type = GiftSystemConst.PrivilegeUIType.Level
  })
  local list = self:GetPrivilegeTemplateList()
  local unlockList = {}
  local lockList = {}
  for _, template in pairs(list) do
    if self.giftLevel >= tonumber(template.level) then
      table.insert(unlockList, {
        type = GiftSystemConst.PrivilegeUIType.Content,
        Unlock = true,
        template = template
      })
    else
      table.insert(lockList, {
        type = GiftSystemConst.PrivilegeUIType.Content,
        Unlock = false,
        template = template
      })
    end
  end
  table.sort(unlockList, function(a, b)
    return a.template.id < b.template.id
  end)
  table.sort(lockList, function(a, b)
    return a.template.id < b.template.id
  end)
  local level = -1
  for i, v in ipairs(lockList) do
    if level < v.template.level then
      v.showLevel = true
      level = v.template.level
    end
  end
  if 0 < #unlockList then
    table.insert(self.privilegeList, {
      type = GiftSystemConst.PrivilegeUIType.Title,
      Unlock = true
    })
    table.insertto(self.privilegeList, unlockList)
  end
  if 0 < #lockList then
    table.insert(self.privilegeList, {
      type = GiftSystemConst.PrivilegeUIType.Title,
      Unlock = false
    })
    table.insertto(self.privilegeList, lockList)
  end
  return self.privilegeList
end

function GiftSystemManager:GetPrivilegeTemplateList()
  if self.privilegeTemplateList ~= nil then
    return self.privilegeTemplateList
  end
  self.privilegeTemplateList = {}
  LocalController:instance():visitTable(TableName.LW_GIFT_PRIVILEGE, function(id, lineData)
    local rowData = {}
    rowData.id = lineData.id
    rowData.level = lineData.level
    rowData.des = lineData.des
    rowData.type = lineData.type
    rowData.icon = lineData.icon
    rowData.para = lineData.para
    table.insert(self.privilegeTemplateList, rowData)
  end)
  table.sort(self.privilegeTemplateList, function(a, b)
    return tonumber(a.level) < tonumber(b.level)
  end)
  return self.privilegeTemplateList
end

function GiftSystemManager:GetNeedExpByLevel(level)
  if self.maxLevel == nil then
    self.maxLevel = LocalController:instance():GetTableLength(TableName.LW_GIFT_LEVEL)
  end
  level = math.min(level, self.maxLevel)
  if self.expList[level] then
    return self.expList[level].exp
  end
  local rowData = LocalController:instance():getLine(TableName.LW_GIFT_LEVEL, level)
  self.expList[level] = rowData
  return rowData.exp
end

function GiftSystemManager:GetGiftLevel()
  return math.max(MinGiftLevel, self.giftLevel)
end

function GiftSystemManager:GetGiftExp()
  return self.giftExp
end

function GiftSystemManager:IsGiftExpired(id)
  local expiredExchangeTemplate = DataCenter.ItemExchangeManager:GetItemExchangeTemplateByItemId(id)
  if expiredExchangeTemplate ~= nil and expiredExchangeTemplate:IsExpiredNow() then
    return true
  end
  return false
end

function GiftSystemManager:GetGiftExpiredTime(id)
  local time = 0
  local exchangeServerData = DataCenter.ItemExchangeManager:GetItemExchangeServerDataById(tonumber(id))
  if exchangeServerData and exchangeServerData.expireTime then
    time = exchangeServerData.expireTime
  end
  return time
end

function GiftSystemManager:GetOriginId(itemId)
  if self.idMap == nil then
    self.idMap = {}
    local list = self:GetGiftGoodsList()
    for _, v in pairs(list) do
      self.idMap[tonumber(v.convert_item)] = tonumber(v.id)
    end
  end
  return self.idMap and self.idMap[tonumber(itemId)]
end

function GiftSystemManager:HasPrivilegeClaimed(id)
  if self.claimedPrivileges == nil then
    return false
  end
  return self.claimedPrivileges[tonumber(id)] == true
end

function GiftSystemManager:CheckPrivilegeHaveRedDot()
  local isHave = false
  local list = self:GetPrivilegeTemplateList()
  for _, template in pairs(list) do
    if self.giftLevel >= tonumber(template.level) and self:HasPrivilegeClaimed(template.id) == false then
      isHave = true
      break
    end
  end
  return isHave
end

function GiftSystemManager:SendGift(itemId, targetUid, isAnonymous, context, num)
  local now = UITimeManager:GetInstance():GetServerTime()
  if self.lastSendTime ~= -1 and now - self.lastSendTime < 1000 then
    return
  end
  self.lastSendTime = now
  if LuaEntry.Player.level < self.minSendGiftLevel and DataCenter.BuildManager.MainLv < self.minSendGiftLevel then
    UIUtil.ShowTips(Localization:GetString("gift_sent_toast3", self.minSendGiftLevel))
    return
  end
  SFSNetwork.SendMessage(MsgDefines.SendUserGift, {
    targetUid = targetUid,
    itemId = itemId,
    num = num,
    context = context,
    isAnonymous = isAnonymous
  })
end

function GiftSystemManager:SendGiftByFollow(itemId, targetUid, isAnonymous, context, num)
  if LuaEntry.Player.level < self.minSendGiftLevel and DataCenter.BuildManager.MainLv < self.minSendGiftLevel then
    UIUtil.ShowTips(Localization:GetString("gift_sent_toast3", self.minSendGiftLevel))
    return
  end
  SFSNetwork.SendMessage(MsgDefines.UserAddFollow, {
    targetUid = targetUid,
    itemId = itemId,
    num = num,
    context = context,
    isAnonymous = isAnonymous
  })
end

function GiftSystemManager:RequestReceivingHistory()
  SFSNetwork.SendMessage(MsgDefines.GiftOwnerReceivingHistory, {
    targetUid = targetUid,
    itemId = itemId
  })
end

function GiftSystemManager:RequestReceivingHistoryById(targetUid, itemId, startIndex, endIndex, filterContent)
  if targetUid then
    SFSNetwork.SendMessage(MsgDefines.GiftOtherReceivingHistory, {
      targetUid = targetUid,
      itemId = itemId,
      startIndex = startIndex,
      endIndex = endIndex
    })
  else
    SFSNetwork.SendMessage(MsgDefines.GiftOwnerReceivingHistory, {
      itemId = itemId or 0,
      startIndex = startIndex,
      endIndex = endIndex
    }, filterContent)
  end
end

function GiftSystemManager:RequestSetGiftShow(arr)
  local list = {}
  local map = {}
  for _, v in ipairs(arr) do
    if not map[v.itemId] then
      map[v.itemId] = v
      if v.pos <= 6 and v.pos > 0 and #list < 6 and 0 < v.count then
        table.insert(list, v)
      end
    end
  end
  SFSNetwork.SendMessage(MsgDefines.SetGiftShow, {arr = list})
end

function GiftSystemManager:RequestGetPrivilegeReward(id)
  SFSNetwork.SendMessage(MsgDefines.UserGiftReward, {id = id})
end

function GiftSystemManager:HandleGiftReceiving(list)
  EventManager:GetInstance():Broadcast(EventId.GiftSystemReceivingHistory, list)
end

function GiftSystemManager:HandleAddGift(data)
end

function GiftSystemManager:HandleSendGift(data)
  self.giftLevel = tonumber(data.level) or MinGiftLevel
  self.giftExp = tonumber(data.exp) or 0
  local name = data.otherPlayerInfo and data.otherPlayerInfo.name or ""
  local template = DataCenter.ItemTemplateManager:GetItemTemplate(data.itemId)
  local tip = data.isAnonymous == 1 and "gift_sent_toast2" or "gift_sent_toast1"
  local giftName = Localization:GetString(template.name)
  UIUtil.ShowTips(Localization:GetString(tip, name .. " ", data.num, giftName))
  local goods = self:GetGiftGoods(data.itemId)
  if goods.ep_gift == 1 then
    local id = data.chatGiftUuid
    DataCenter.GiftSystemManager:TryPlayAnim(id, goods.id)
  elseif next(goods.group_id) then
    local index = 0
    for i, v in ipairs(goods.group_id) do
      if data.num >= tonumber(v) then
        index = i
      end
    end
    local effect = goods.group_effect[index]
    if not string.IsNullOrEmpty(effect) then
      local id = data.chatGiftUuid
      DataCenter.GiftSystemManager:TryPlayAnim(id, goods.id, index)
    end
  end
end

function GiftSystemManager:HandleGiftReceivingHistory(list, params)
  if params and params.filterContent and params.filterContent > 0 then
    EventManager:GetInstance():Broadcast(EventId.GiftReceivingFilterMsgHistory, list)
  else
    EventManager:GetInstance():Broadcast(EventId.GiftSystemReceivingHistory, list)
  end
end

function GiftSystemManager:HandleGetPrivilegeReward(data)
  DataCenter.RewardManager:ShowCommonReward(data)
  DataCenter.RewardManager:AddRewardsAndRes(data)
  self.claimedPrivileges[tonumber(data.id)] = true
  EventManager:GetInstance():Broadcast(EventId.GiftSystemReceivingPrivilege)
end

function GiftSystemManager:InitAnim()
  self.canPlayEffect = CommonUtil.PlayerPrefsGetBool(CAN_PLAY_EFFECT_KEY, true)
  self.animHistory = CommonUtil.PlayerPrefsGetTable(GIFT_EFFECT_HISTORY_LIST, {})
  local now = UITimeManager:GetInstance():GetServerTime()
  local list = {}
  for _, v in pairs(self.animHistory) do
    if 8640000 < now - v then
      table.insert(list, v)
    end
  end
  if 0 < #list then
    for _, v in ipairs(list) do
      self.animHistory[v] = nil
    end
    CommonUtil.PlayerPrefsSetTable(GIFT_EFFECT_HISTORY_LIST, self.animHistory)
  end
end

function GiftSystemManager:TryPlayAnimOnlyAni(giftId, groupId)
  local data = {giftId = giftId, groupId = groupId}
  if UIManager:GetInstance():IsWindowOpen(UIWindowNames.LWUIGiftSpecialAnimShow) then
    EventManager:GetInstance():Broadcast(EventId.GiftSystemPlayEffect, data)
  else
    UIManager:GetInstance():OpenWindow(UIWindowNames.LWUIGiftSpecialAnimShow, {anim = true}, data)
  end
end

function GiftSystemManager:TryPlayAnim(seqId, giftId, groupId)
  if not self.canPlayEffect then
    return
  end
  if self.animHistory[tostring(seqId)] then
    return
  end
  local now = UITimeManager:GetInstance():GetServerTime()
  self.animHistory[tostring(seqId)] = now
  local anim = self.animQueen[#self.animQueen]
  if anim and anim.giftId == giftId then
    return
  end
  if self.animPlaying and giftId == self.animPlayingId then
    return
  end
  table.insert(self.animQueen, {
    seqId = seqId,
    giftId = giftId,
    groupId = groupId
  })
  self:QueenPlayAnim()
end

function GiftSystemManager:QueenPlayAnim()
  if self.animPlaying then
    return
  end
  if #self.animQueen <= 0 then
    return
  end
  self.animPlaying = true
  local info = table.remove(self.animQueen, 1)
  self.animPlayingId = info.giftId
  local data = {
    giftId = info.giftId,
    groupId = info.groupId,
    callback = function()
      self.animPlaying = false
      self.animPlayingId = nil
      if #self.animQueen <= 0 then
      else
        self:QueenPlayAnim()
      end
    end
  }
  CommonUtil.PlayerPrefsSetTable(GIFT_EFFECT_HISTORY_LIST, self.animHistory)
  if UIManager:GetInstance():IsWindowOpen(UIWindowNames.LWUIGiftSpecialAnimShow) then
    EventManager:GetInstance():Broadcast(EventId.GiftSystemPlayEffect, data)
  else
    UIManager:GetInstance():OpenWindow(UIWindowNames.LWUIGiftSpecialAnimShow, {anim = true}, data)
  end
end

function GiftSystemManager:GetGiftEffectState()
  return self.canPlayEffect
end

function GiftSystemManager:SwitchGiftEffectState()
  self.canPlayEffect = not self.canPlayEffect
  CommonUtil.PlayerPrefsSetBool(CAN_PLAY_EFFECT_KEY, self.canPlayEffect)
end

function GiftSystemManager:OpenOperationView(data)
  UIManager:GetInstance():OpenWindow(UIWindowNames.LWUIGiftOperation_v2, {anim = true}, data)
end

function GiftSystemManager:OpenDetailView(param, isNewUI)
  local template = param.template
  local goods = self:GetGiftGoods(template.id)
  if goods.group_id and next(goods.group_id) then
    UIManager:GetInstance():OpenWindow(UIWindowNames.LWUIGroupGiftDetail, {anim = true}, param)
    return
  end
  UIManager:GetInstance():OpenWindow(UIWindowNames.LWUIGiftDetail_v2, {anim = true}, param)
end

GiftSystemManager.__init = __init
GiftSystemManager.__delete = __delete
GiftSystemManager.AddListener = AddListener
GiftSystemManager.RemoveListener = RemoveListener
GiftSystemManager.InitData = InitData
return GiftSystemManager
