local this = class("photoManager", G_EventManagerBase)
table.merge(this, require("ui.manager.photo.photoManager_logic"))
table.merge(this, require("ui.manager.photo.photoManager_temp"))
local _res4kSize = {x = 3840, y = 2160}
this.event = {
  photoCaptureFinish = "photoCaptureFinish",
  removePhotoPetEntity = "removePhotoPetEntity",
  addPhotoPetEntity = "addPhotoPetEntity",
  clearAllPhotoPetEntity = "clearAllPhotoPetEntity",
  photoMenuStateChange = "photoMenuStateChange",
  photoMenuForceRefresh = "photoMenuForceRefresh",
  selectPhotoHeroChange = "selectPhotoHeroChange",
  photoSettingChange = "photoSettingChange",
  photoTemplateChange = "photoSettingChange",
  photoSwitchHero = "photoSwitchHero",
  photoEditSave = "photoEditSave",
  pagePhotoOpen = "pagePhotoOpen"
}

function this:ctor()
  this.super.ctor(self)
  self._obj2Entity = {}
  self:initPhotoPetEntityInfo()
  self:initTemplateData()
  self.moduleGroupHero = nil
  if not self.util then
    self.util = require("ui.manager.photo.photoUtil")
  end
  self.actionCollectCache = {}
  self.faceCollectCache = {}
end

function this:capture(callback, width, height, isPhotoMain)
  if L_PhotoManager.useHighResolution and isPhotoMain then
    width = _res4kSize.x
    height = _res4kSize.y
  end
  local uiCamera = L_CameraManager:getUICamera()
  local souMask = uiCamera.cullingMask
  uiCamera.cullingMask = 0
  uiCamera:SingleLayerTrans(L_Const.layer.photo)
  width = width or C_Screen.width
  height = height or C_Screen.height
  local rt = C_RenderTexture.GetTemporary(width, height)
  C_CameraManager.uiCamera:Capture(rt, false, true, function()
    uiCamera.cullingMask = souMask
    if callback then
      callback(rt)
    end
    print("[\230\139\141\231\133\167\229\137\167\230\131\133Log] Lua sendEvent photoCaptureFinish")
    self:sendEvent(this.event.photoCaptureFinish)
  end)
end

function this:screenHeadShot(rect, cameraList, imgType, callback)
  local width = math.ceil(rect.width)
  local height = math.ceil(rect.height)
  local tex = Unity.Texture2D(width, height, Unity.TextureFormat.RGBA32, false)
  for _, v in ipairs(cameraList) do
    C_CameraCaptureUtil.CaptureFrameToTexture2D2(v, tex, rect)
  end
  tex = C_CameraCaptureUtil.HorizontalFlipTexture(tex)
  local uploadKey = {
    L_PhotoStore.path.imgCDNPath,
    L_PlayerStore:getPlayerId(),
    "_",
    imgType,
    "_",
    tostring(C_HttpManager.ConvertDataTime())
  }
  local _onSuccess = function(key)
    local strArr = string.split(key, "/")
    key = strArr[#strArr]
    local path = self:getHeadTexFilePath(key)
    C_PhotoManager.SaveTexture2DByPath(path, tex, false)
    if callback then
      callback(true, key)
    end
  end
  local _onFail = function(message)
    if callback then
      if CS.UnityEngine.Application.isEditor then
        _onSuccess(uploadKey)
        return
      end
      callback(false, message)
    end
  end
  local texData = Unity.ImageConversion.EncodeToPNG(tex)
  uploadKey = table.concat(uploadKey)
  C_CDNManager.TransferUploadBytes(texData, uploadKey, _onSuccess, _onFail)
  return tex
end

function this:shotByRectTrans(rectTrans, camera)
  local pos = L_Vector3.getAnchored(rectTrans)
  local rect = C_Rect(pos.x, pos.y, rectTrans.rect.width, rectTrans.rect.height)
  local width = math.ceil(rect.width)
  local height = math.ceil(rect.height)
  local tex = Unity.Texture2D(width, height, Unity.TextureFormat.RGBA32, false)
  C_CameraCaptureUtil.CaptureFrameToTexture2D2(camera, tex, rect)
  tex = C_CameraCaptureUtil.HorizontalFlipTexture(tex)
  return tex
end

function this:downloadHeadTexure(name, callback, cdnPath, savePath)
  local loadNum = 1
  
  local function getCallback(flag, tex, errorKey)
    if flag then
      if not string.isEmpty(savePath) then
        C_PhotoManager.SaveTexture2DByPath(savePath, tex)
      end
    elseif loadNum <= 3 then
      loadNum = loadNum + 1
      self:getScreenShotHead(name, getCallback, cdnPath)
    else
      errorf(string.format("%s download fail: %s", name, tostring(errorKey)))
    end
    if callback then
      callback(tex)
    end
  end
  
  self:getScreenShotHead(name, getCallback, cdnPath)
end

function this:getScreenShotHead(url, callback, cdnPath)
  cdnPath = cdnPath or L_PhotoStore.path.imgCDNPath
  url = url or ""
  url = cdnPath .. url
  local successCall = function(self, tex)
    L_PhotoStore:call(L_PhotoStore.event.photoFinishGet, {url = url, tex = tex})
    if callback then
      callback(true, tex)
    end
  end
  local failCall = function(self, key)
    if callback then
      callback(false, nil, key)
    end
  end
  C_CDNManager.DownloadToTex(url, handler(self, successCall), handler(self, failCall))
end

function this:getHeadTexFilePath(name, customPath)
  local path = ""
  local strArr = string.split(name, "_")
  if not string.isEmpty(strArr[2]) then
    customPath = customPath or L_PhotoStore.path.imgSavePath
    path = customPath .. strArr[2]
  end
  return string.format("%s/%s.png", path, name)
end

function this:loadHeadTex(name, callback, customPath, cdnPath)
  if string.isEmpty(name) then
    callback()
    return
  end
  local imgFilePath = self:getHeadTexFilePath(name, customPath)
  if C_File.Exists(imgFilePath) then
    C_PhotoManager.GetTexture2DByPath(imgFilePath, callback)
  else
    self:downloadHeadTexure(name, callback, cdnPath, imgFilePath)
  end
end

function this:checkHeadTex()
  local path = L_PlayerStore:getAvatarTexturePath(L_Const.avatarTextureIndex.painting)
  if path ~= L_CommonUtil.getLocalValue("CheckHeadTex") then
    L_CommonUtil.setLocalValue("CheckHeadTex", path)
    self:predownloadHeadTex(L_Const.avatarTextureIndex.painting)
    self:predownloadHeadTex(L_Const.avatarTextureIndex.half_formation)
    self:predownloadHeadTex(L_Const.avatarTextureIndex.head)
    self:predownloadHeadTex(L_Const.avatarTextureIndex.head_circle)
    self:predownloadHeadTex(L_Const.avatarTextureIndex.head_talk)
    self:predownloadHeadTex(L_Const.avatarTextureIndex.body)
  end
end

function this:predownloadHeadTex(avatarTextureIndex)
  local name = L_PlayerStore:getAvatarTexturePath(avatarTextureIndex)
  local imgFilePath = self:getHeadTexFilePath(name)
  if not C_File.Exists(imgFilePath) then
    self:downloadHeadTexure(name, nil, nil, imgFilePath)
  end
end

function this:newOrBindPhotoEntity(obj, go, url)
  if string.isEmpty(url) then
    return
  end
  self._obj2Entity[obj] = self._obj2Entity[obj] or require("ui.manager.photo.photoEntity").new()
  self._obj2Entity[obj]:bindGameObject(go)
  self._obj2Entity[obj]:setImgName(url)
end

function this:clearPhotoEntity(obj)
  if self._obj2Entity[obj] then
    self._obj2Entity[obj]:dispose()
  end
end

function this:bindPhotoEntity(go, url)
  local photoEntity = require("ui.manager.photo.photoEntity").new()
  photoEntity:bindGameObject(go)
  photoEntity:setImgName(url)
  return photoEntity
end

function this:fillMainHead(bind, img_icon, playerId, index)
  if index == nil then
    index = L_Const.avatarTextureIndex.head
  end
  local modName = L_PlayerStore:getAvatarTexturePath(index)
  if not string.isEmpty(modName) then
    if bind.photoEntity == nil then
      bind.photoEntity = self:bindPhotoEntity(img_icon, modName)
    else
      bind.photoEntity:bindGameObject(img_icon)
      bind.photoEntity:setImgName(modName)
    end
  elseif bind.photoEntity then
    bind.photoEntity:dispose()
  end
end

function this:releaseHead(bind)
  if bind.photoEntity then
    bind.photoEntity:dispose()
  end
end

function this:initPhotoPetEntityInfo()
  self.entitys = {}
  self.insIndex = 0
  self.selectEntityGuid = nil
end

function this:getPhotoPetEntityIndex()
  self.insIndex = self.insIndex + 1
  return self.insIndex
end

function this:getPhotoPetEntityCount()
  local count = 0
  for key, value in pairs(self.entitys) do
    count = count + 1
  end
  return count
end

function this:getAllPhotoPetEntity()
  return self.entitys
end

function this:setPhotoPetEntityInfo(info)
  self.curSelectEntityInfo = info
end

function this:getSelectPhotoPetEntity()
  return self.curSelectEntityInfo and self.curSelectEntityInfo.entity
end

function this:addPhotoPetEntity(guid, endCallback)
  local info = {}
  info.index = self:getPhotoPetEntityIndex()
  info.guid = guid
  info.actionId = L_Const.photoParam.petDefAction
  local petItem = L_PetStore:getPetItem(guid)
  self.entitys[info.index] = info
  info.entityId = L_EntityManager:generatePhotoPetEntity(petItem, function(entity)
    if self.entitys[info.index] then
      local mainEntity = L_PlayerManager:getMainControlEntity()
      local pos = mainEntity:getPosition()
      entity:setPosition(pos)
      info.entity = entity
      info.cachePos = entity.goModel.transform.position
      info.cacheRotation = entity:getRotation()
      if endCallback then
        endCallback(info)
      end
      self:sendEvent(this.event.addPhotoPetEntity, info.guid)
      self:sendEvent(this.event.photoMenuForceRefresh)
    else
      L_EntityManager:destroyEntity(entity)
    end
  end)
end

function this:removePhotoPetEntity(index, callback)
  local info = self.entitys[index]
  self.entitys[index] = nil
  if info then
    if info.entity then
      L_EntityManager:destroyEntity(info.entity)
    else
      L_CsEntityManager:removeEntityWithEntityId(info.entityId)
    end
    if callback then
      callback()
    end
    self:sendEvent(this.event.removePhotoPetEntity, info.guid)
    self:sendEvent(this.event.photoMenuForceRefresh)
  end
end

function this:clearAllPhotoPetEntity()
  for _, v in pairs(self.entitys) do
    if v.entity then
      L_EntityManager:destroyEntity(v.entity)
    else
      L_CsEntityManager:removeEntityWithEntityId(v.entityId)
    end
  end
  self:initPhotoPetEntityInfo()
  self:sendEvent(this.event.clearAllPhotoPetEntity)
  self:sendEvent(this.event.photoMenuForceRefresh)
end

function this:checkPhotoCanTouchClick(noShowMsg)
  local canTouch = true
  if self.selectEntityGuid then
    canTouch = false
    if not noShowMsg then
      L_FlyMsgManager:showNormalMsgByKey("notice_modulePhotoGroup_hero_01")
    end
  end
  return canTouch
end

function this:checkPetCanSet(id)
  local count = 0
  for _, v in pairs(self.entitys) do
    if v.guid == id then
      count = count + 1
    end
  end
  return count <= 0
end

function this:checkCanSwitchHero(guid)
  if self.moduleGroupHero == nil then
    return true
  end
  local putInfo = self.moduleGroupHero.heroPutInfo
  for i, v in pairs(putInfo) do
    if guid == i then
      return false
    end
  end
  return true
end

function this:setCollectAction(id, isCollect)
  local key = string.format("photo_action_collect_%d", id)
  local timeKey = string.format("photo_action_collectTime_%d", id)
  if isCollect then
    L_CommonUtil.setLocalBoolValue(key, true)
    L_CommonUtil.setLocalValue(timeKey, L_TimeUtil.getServerTime())
  else
    L_CommonUtil.clearLocalValue(key)
    L_CommonUtil.clearLocalValue(timeKey)
  end
  self.actionCollectCache[id] = {
    isOn = isCollect,
    time = isCollect and L_TimeUtil.getServerTime() or nil
  }
end

function this:checkCollectAction(id)
  local cache = self.actionCollectCache[id]
  if cache == nil then
    local key = string.format("photo_action_collect_%d", id)
    local timeKey = string.format("photo_action_collectTime_%d", id)
    local data = L_CommonUtil.getLocalBoolValue(key)
    if data == true then
      local time = L_CommonUtil.getLocalValue(timeKey)
      self.actionCollectCache[id] = {
        isOn = true,
        time = tonumber(time)
      }
      return self.actionCollectCache[id]
    else
      self.actionCollectCache[id] = {isOn = false, time = nil}
      return self.actionCollectCache[id]
    end
  else
    return cache
  end
end

function this:setCollectFace(id, isCollect)
  local key = string.format("photo_face_collect_%d", id)
  local timeKey = string.format("photo_face_collectTime_%d", id)
  if isCollect then
    L_CommonUtil.setLocalBoolValue(key, true)
    L_CommonUtil.setLocalValue(timeKey, L_TimeUtil.getServerTime())
  else
    L_CommonUtil.clearLocalBoolValue(key)
    L_CommonUtil.clearLocalValue(timeKey)
  end
  self.faceCollectCache[id] = {
    isOn = isCollect,
    time = isCollect and L_TimeUtil.getServerTime() or nil
  }
end

function this:checkCollectFace(id)
  local cache = self.faceCollectCache[id]
  if cache == nil then
    local key = string.format("photo_face_collect_%d", id)
    local timeKey = string.format("photo_face_collectTime_%d", id)
    local data = L_CommonUtil.getLocalBoolValue(key)
    if data == true then
      local time = L_CommonUtil.getLocalValue(timeKey)
      self.faceCollectCache[id] = {
        isOn = true,
        time = tonumber(time)
      }
      return self.faceCollectCache[id]
    else
      self.faceCollectCache[id] = {isOn = false, time = nil}
      return self.faceCollectCache[id]
    end
  else
    return cache
  end
end

return this
