local this = class("cameraManager", G_EventManagerBase)
this.event = {blendStart = "blendStart", blendEnd = "blendEnd"}

function this:ctor(...)
  this.super.ctor(self, ...)
  self.blendStyleDic = {}
  self.camControllerDic = {}
  self.lastCamController = nil
  self.curCamContorller = nil
  self.blendTimer = nil
  self.transBindPoint = nil
end

function this:init()
  self.cameraZoomOutHandle = self.cameraZoomOutHandle or handler(self, self.cameraZoomOut)
  C_ExternalManager.AddEvent(C_EExternalEventType.CameraZoomOut, self.cameraZoomOutHandle)
  self.cameraZoomInHandle = self.cameraZoomInHandle or handler(self, self.cameraZoomIn)
  C_ExternalManager.AddEvent(C_EExternalEventType.CameraZoomIn, self.cameraZoomInHandle)
end

function this:dispose()
  C_ExternalManager.RemoveEvent(C_EExternalEventType.CameraZoomOut, self.cameraZoomOutHandle)
  C_ExternalManager.RemoveEvent(C_EExternalEventType.CameraZoomIn, self.cameraZoomInHandle)
end

function this:cameraZoomOut()
  if L_UI:getPage("pageFaceIn") ~= nil then
    L_UI:close("pageFaceIn")
  end
end

function this:cameraZoomIn()
  if L_UI:getPage("pagePhoto") == nil then
    L_UI:open("pageFaceIn")
  end
end

function this:switchToWorld()
  return self:switchTo(L_Const.cameraMode.world)
end

function this:switchToStory()
  return self:switchTo(L_Const.cameraMode.story)
end

function this:switchToBattle()
  return self:switchTo(L_Const.cameraMode.battle)
end

function this:switchToFishing()
  return self:switchTo(L_Const.cameraMode.fishing)
end

function this:switchToNpcKiBoDuel()
  local style = self:getBlendStyle(L_Const.blendStyleMode.custom)
  style.time = 1000
  return self:switchTo(L_Const.cameraMode.npcKiBoDuel, style)
end

function this:switchToNpcEntrustTask()
  local style = self:getBlendStyle(L_Const.blendStyleMode.custom)
  style.time = 1000
  return self:switchTo(L_Const.cameraMode.npcEntrustTask, style)
end

function this:switchToNpcShop()
  local style = self:getBlendStyle(L_Const.blendStyleMode.custom)
  style.time = 1000
  return self:switchTo(L_Const.cameraMode.npShop, style)
end

function this:switchToDungeon()
  return self:switchTo(L_Const.cameraMode.dungeon)
end

function this:switchToCollection()
  return self:switchTo(L_Const.cameraMode.collection)
end

function this:switchToHomeBuild()
  local blendStyle = L_CameraManager:getBlendStyle(L_Const.blendStyleMode.easeInOut)
  blendStyle.time = 800
  return self:switchTo(L_Const.cameraMode.homeBuild, blendStyle)
end

function this:switchToUiScene()
  return self:switchTo(L_Const.cameraMode.uiScene)
end

function this:switchToSubItem()
  return self:switchTo(L_Const.cameraMode.subItem)
end

function this:switchToPhoto()
  return self:switchTo(L_Const.cameraMode.photo)
end

function this:switchToPhotographPoint()
  return self:switchTo(L_Const.cameraMode.photographPoint)
end

function this:switchToMenu()
  local style = self:getBlendStyle(L_Const.blendStyleMode.custom)
  style.time = 300
  return self:switchTo(L_Const.cameraMode.menu, style)
end

function this:revertMenu()
  local style = self:getBlendStyle(L_Const.blendStyleMode.easeOut)
  local mainControl = L_PlayerManager:getMainControlEntity()
  local povH = 0
  if mainControl then
    local rot = L_Vector3.getRot(mainControl:getTransform())
    povH = povH + rot.y
  end
  style:setBlendParams({
    time = 300,
    switchInParams = {
      povH = povH,
      povV = 25,
      distance = 3
    }
  })
  return self:revertCamController(style)
end

function this:revertCamController(blendStyle)
  print("revertCamController")
  if self.lastCamController == nil then
    return
  end
  print(self.lastCamController:getMode())
  return self:switchTo(self.lastCamController:getMode(), blendStyle)
end

function this:switchTo(nextMode, blendStyle)
  blendStyle = blendStyle or self:getBlendStyle(L_Const.blendStyleMode.cut)
  local preMode = self:getCameraMode()
  local isChanged = preMode ~= nextMode
  if isChanged then
    local switchOut = function(switchOutParams)
      if self.lastCamController then
        self.lastCamController:switchOut(nextMode, switchOutParams)
      end
      self.blendStyle = nil
      self:sendEvent(this.event.blendEnd)
    end
    if self.blendStyle then
      self.blendStyle:stopBlend()
    end
    blendStyle:addCallback(switchOut)
    local controller = self:getCamController(nextMode, true)
    self.lastCamController = self.curCamContorller
    self.curCamContorller = controller
    self.curCamContorller:switchIn(preMode, blendStyle.switchInParams)
    self.curCamContorller:setBlendStyle(blendStyle.style, blendStyle.time)
    self:sendEvent(this.event.blendStart)
    blendStyle:startBlend()
    self.blendStyle = blendStyle
  end
  return self.curCamContorller
end

function this:setCameraSpeed()
  for i, v in pairs(self.camControllerDic) do
    v:setCameraSpeed()
  end
end

function this:getCamController(mode, isCreate)
  local camContorller = self.camControllerDic[mode]
  local isNew = false
  if camContorller == nil and isCreate then
    camContorller = require("ui.manager.camera.controller.cameraController_" .. mode).new(mode)
    self.camControllerDic[mode] = camContorller
    isNew = true
  end
  return camContorller, isNew
end

function this:getBlendStyle(style)
  local blendStyle = self.blendStyleDic[style]
  if blendStyle == nil then
    blendStyle = require("ui.manager.camera.blendMode.blendStyle_" .. style).new()
    self.blendStyleDic[style] = blendStyle
  else
    blendStyle:init()
  end
  return blendStyle
end

function this:getCurCamController()
  return self.curCamContorller
end

function this:getCameraMode()
  return self.curCamContorller and self.curCamContorller:getMode()
end

function this:getCameraTactics()
  return self.curCamContorller and self.curCamContorller:getCameraTactics()
end

function this:getLastCamController()
  return self.lastCamController
end

function this:getLastCameraMode()
  return self.lastCamController and self.lastCamController:getMode()
end

function this:getSceneCamera()
  return C_CameraManager.mainCamera
end

function this:getSceneCameraTransform()
  return self:getSceneCamera().transform
end

function this:getUICamera()
  return C_CameraManager.uiCamera
end

function this:setClearFlag(flag)
  if L_UI:checkPageOpen("pagePlatformLogin") then
    C_CameraManager.SetMainCameraClearFlags(CS.UnityEngine.CameraClearFlags.Skybox)
    return
  end
  C_CameraManager.SetMainCameraClearFlags(flag)
end

function this:getIsControlWithMouse()
  local isControl = C_CameraManager.isControlWithMouse
  return isControl
end

function this:getShowCursor()
  local result = C_CameraManager.showCursor
  return result
end

function this:getCameraNode()
  return C_CameraManager.GetCameraNode()
end

function this:getBrain()
  local brain = C_CameraManager.GetMainCameraBrain()
  return brain
end

function this:getVirCamera()
  return self.curCamContorller and self.curCamContorller:getVirCamera()
end

function this:getFixedFollow()
  return self.curCamContorller and self.curCamContorller.fixedFollow
end

function this:destroyCurCamController()
  if self.curCamContorller == nil then
    return
  end
  self.curCamContorller:onDestroy()
  self.camControllerDic[self.curCamContorller:getMode()] = nil
  self.curCamContorller = nil
end

function this:bindEntity(entity, isQuick)
  if self.curCamContorller == nil then
    return
  end
  self.curCamContorller:bindEntity(entity)
  if isQuick ~= false then
    self:updateCameraStateImmediately()
  end
end

function this:bindTargetTransform(transform, isQuick)
  if self.curCamContorller == nil then
    return
  end
  self.curCamContorller:bindTransform(transform)
  if isQuick ~= false then
    self:updateCameraStateImmediately()
  end
end

function this:bindGameObject(go, isQuick)
  if self.curCamContorller == nil then
    return
  end
  self.curCamContorller:bindGameObject(go)
  if isQuick ~= false then
    self:updateCameraStateImmediately()
  end
end

function this:bindPoint(lookPos, lookRot, isQuick)
  if self.curCamContorller == nil then
    return
  end
  if self.transBindPoint == nil then
    self.transBindPoint = C_GameObject("virtualPoint").transform
    self.transBindPoint:SetParent(C_LuaUtility.GetRootNode())
  end
  local pos = lookPos or L_Vector3.getTemp()
  self.transBindPoint.localPosition = C_Vector3(pos.x, pos.y, pos.z)
  local rot = lookRot or L_Vector3.getTemp()
  self.transBindPoint.localEulerAngles = C_Vector3(rot.x, rot.y, rot.z)
  self:bindGameObject(self.transBindPoint.gameObject, isQuick)
  L_CameraManager:setVirCamerPOVHV(lookRot and lookRot.y or 0, 0)
end

function this:refreshVirCameraOffset(...)
  if self.curCamContorller == nil then
    return
  end
  self.curCamContorller:refreshVirCameraOffset(...)
end

function this:setVirCameraScaleView(canScale)
  C_CameraManager.uiCanScaleView = canScale
end

function this:getWorldCameraTacticsManager()
  self.worldCameraTactics = self.worldCameraTactics or C_CameraTacticsManager()
  return self.worldCameraTactics
end

function this:setVirCamerPOVHV(h, v)
  if self.curCamContorller == nil then
    return
  end
  local tactics = self.curCamContorller:getCameraTactics()
  if h and v then
    tactics:SetCameraPOVHV(h, v)
  elseif h then
    tactics:SetCameraPOVHorizontal(h)
  elseif v then
    tactics:SetCameraPOVVertical(v)
  end
end

function this:getCameraDis()
  if self.curCamContorller == nil then
    return 0
  end
  local tactics = self.curCamContorller:getCameraTactics()
  local val = tactics:GetCameraDis()
  return val
end

function this:getFov()
  if self.curCamContorller == nil then
    return 0
  end
  local tactics = self.curCamContorller:getCameraTactics()
  local val = tactics:GetCameraFov()
  return val
end

function this:updateCameraStateImmediately()
  if self.curCamContorller == nil then
    return
  end
  local brain = self:getBrain()
  local virCamera = self.curCamContorller:getVirCamera()
  if brain and virCamera then
    local worldUp = brain.DefaultWorldUp
    virCamera:InternalUpdateCameraState(worldUp, 1000)
    brain:ManualUpdate()
  end
end

return this
