local this = class("pagePhotographPlayable", G_UIPageBase)

function this.bind()
  return {
    main = true,
    goWhiteCut = false,
    photo = false,
    playerInfo = true,
    playerId = "",
    playerName = "",
    dim = false,
    angle = 0,
    targetSearchTipNode = false,
    targetAniActive = false,
    searchActive = false,
    joystickCamera = true,
    moduleCommonTop = {
      moduleName = "modulePages/moduleCommonTop"
    }
  }
end

function this.methods()
  return {
    onClick_screenCapture = function(self)
      self.bind.goWhiteCut = true
      L_PhotoManager:capture(function(t2d)
        local t2 = {rt = t2d, isPhotoTask = true}
        L_UI:open("pagePhotoPreview", t2, function()
          self.bind.goWhiteCut = false
          if self.isInTarget then
            self.isRecord = true
            local args = CS.Lens.Gameplay.Modules.BigWorld.CommonIntDriveArgs()
            args.intVal = 1
            C_DriveManager.DispatchDrive(C_EExternalDrive.ProtoPlayableEnd, args)
            L_UI:close(self.pageName)
          end
        end)
        local sceneId = AzurWorldInstance.CurWorldId
        local worldAreaId = L_AreaStore:getMapAreaId()
        L_AchievementStore:req_clientBehaviourRecord(L_Const.commonCondition.RegionPhotoTimes, {
          sceneId,
          worldAreaId,
          1
        }, function()
        end)
      end)
    end,
    onClick_closePhoto = function(self)
    end,
    onClick_savePhoto = function(self)
    end,
    onClick_preBtn = function(self)
      self:setPreCameraPos()
    end,
    onClick_nextBtn = function(self)
      self:setNextCameraPos()
    end
  }
end

function this:fadeIn()
  local data = {
    coverdTime = 0.9,
    fadeOut = true,
    fadeIn = false,
    isCompleteClose = true
  }
  L_GameUtil.openMask(data)
end

function this:check(options, callback)
  if L_BattleDataManager:checkPlayerBattle() then
    L_FlyMsgManager:showNormalMsg(L_BattleDataManager:getBattleBlockTips(L_Const.BattleBlockType.PhotographEntrance))
    callback(false)
    return
  end
  local result = true
  if result then
    result = not L_BattleStore:getIsInBattle() and L_PlayerManager:getMainControlIsFree() and not L_PlayerStore:getIsNewPlayer()
    if not result then
      L_FlyMsgManager:showNormalMsgByKey("notice_pagePhoto_04")
    end
  end
  if result then
    self:fadeIn()
  end
  callback(result)
end

function this:preOpen(options)
  self.cameraRotateSpeed = 3
  self.cameraMoveSpeed = 0.1
  self.showPlayerInfo = true
  self.bind.playerId = tostring(L_PlayerStore:getPlayerId())
  self.bind.playerName = L_PlayerStore:getPlayerName()
  L_ShortCutManager:registerPageMainShortCut()
  L_CameraManager:switchToPhoto()
  L_PlayerManager:stopIdleAnim()
  self.playableObjectList = nil
  self.playableObjectIndex = 1
  self.cameraAngleList = nil
  if options then
    self.playableObjectList = options.playableObjectList
    self.cameraAngleList = options.cameraAngleList
    self.cameraOffsetList = options.cameraOffsetList
    self.isSearchTarget = options.isSearchTarget
    self.targetPos = options.targetPos
    self.distanceLimit = options.distanceLimit
    self.targetGo = options.targetGo
    if self.isSearchTarget then
      self.bind.targetSearchTipNode = self.isSearchTarget
    end
  end
  self:updateCameraPos()
  self:bindScreenTouch("+")
  AzurWorld.HomeMgr:LockAllEffect(true)
  local data = {
    name = L_GameTpl:getWordsTpl():getTplById("notice_umi_lookingfor_02"),
    helpBtnBool = false,
    mainBtnBool = false,
    closeCurPage = function()
      L_UI:close(self.pageName)
    end,
    helpBtn = function()
    end,
    mainBtn = function()
      L_UI:backToRoot()
    end
  }
  self.modules.moduleCommonTop:initModule(data)
end

function this:close(options)
  this.super.close(self, options)
  self:unbindCameraJoystick()
  if self.cameraJoystickTimer then
    Timer.remove(self.cameraJoystickTimer)
  end
  self:DisableCurVirCam()
  self.virtualCamera = nil
  self.photographCamera = nil
  AzurWorld.HomeMgr:LockAllEffect(false)
  self:bindScreenTouch("-")
  L_CameraManager:revertCamController()
  L_PlayerManager:initIdleAnim()
  if not self.isRecord then
    local args = CS.Lens.Gameplay.Modules.BigWorld.CommonIntDriveArgs()
    args.intVal = 2
    C_DriveManager.DispatchDrive(C_EExternalDrive.ProtoPlayableEnd, args)
  end
  self.isRecord = false
end

function this:show(options)
  this.super.show(self, options)
  L_GameUtil.setJoyStick(self.bindComponents.joystickCamera)
  self:bindCameraJoystick()
end

function this:onCameraJoystickDragStart()
  if not self.cameraJoystickTimer then
    self.cameraJoystickTimer = Timer.repeated(0, function()
      local joystick = self.bindComponents.joystickCamera
      self:moveCamera(-joystick.Horizontal * self.cameraMoveSpeed, joystick.Vertical * self.cameraMoveSpeed)
    end)
  else
    self.cameraJoystickTimer:resume()
  end
end

function this:onCameraJoystickDragEnd()
  if self.cameraJoystickTimer then
    self.cameraJoystickTimer:pause()
  end
end

function this:moveCamera(x, y)
  if self.virtualCamera and self.xNormalized and self.yNormalized then
    self.xOffset = self.xOffset + x
    self.yOffset = self.yOffset + y
    if self.xOffset < -self.maxOffset then
      self.xOffset = -self.maxOffset
    end
    if self.xOffset > self.maxOffset then
      self.xOffset = self.maxOffset
    end
    if self.yOffset < -self.maxOffset then
      self.yOffset = -self.maxOffset
    end
    if self.yOffset > self.maxOffset then
      self.yOffset = self.maxOffset
    end
    self.virtualCamera.transform.position = self.oriPos + L_Vector3.new(self.xOffset * self.xNormalized.x, self.xOffset * self.xNormalized.y, self.xOffset * self.xNormalized.z) + L_Vector3.new(self.yOffset * self.yNormalized.x, self.yOffset * self.yNormalized.y, self.yOffset * self.yNormalized.z)
  end
end

function this:bindCameraJoystick()
  local joystick = self.bindComponents.joystickCamera
  joystick.onPointerDownHandler = L_CommonUtil.handle(self.onCameraJoystickDragStart, self)
  joystick.onPointerUpHandler = L_CommonUtil.handle(self.onCameraJoystickDragEnd, self)
end

function this:unbindCameraJoystick()
  local joystick = self.bindComponents.joystickCamera
  joystick.onPointerDownHandler = nil
  joystick.onPointerUpHandler = nil
end

function this:setPreCameraPos()
  if self.playableObjectList ~= nil then
    self:DisableCurVirCam()
    self.playableObjectIndex = self.playableObjectIndex - 1
    if self.playableObjectIndex <= 0 then
      self.playableObjectIndex = #self.playableObjectList
    end
  end
  self:updateCameraPos()
end

function this:setNextCameraPos()
  if self.playableObjectList ~= nil then
    self:DisableCurVirCam()
    self.playableObjectIndex = self.playableObjectIndex + 1
    if self.playableObjectIndex > #self.playableObjectList then
      self.playableObjectIndex = 1
    end
  end
  self:updateCameraPos()
end

function this:DisableCurVirCam()
  if self.virtualCamera then
    self.virtualCamera.enabled = false
    self.virtualCamera.transform.position = self.oriPos
    self.virtualCamera.transform.forward = self.oriForward
  end
  self.xNormalized = nil
  self.zNormalized = nil
  self.oriPos = nil
  self.oriForward = nil
  self.maxOffset = nil
  self.xOffset = nil
  self.yOffset = nil
  self.cameraValid = nil
end

function this:updateCameraPos()
  self.virtualCamera = nil
  if self.playableObjectList == nil or self.playableObjectList[self.playableObjectIndex] == nil then
  else
    local playableUnitManager = AzurWorld.PlayableUnitMgr
    local playableObjectId = self.playableObjectList[self.playableObjectIndex]
    local playableObject = playableUnitManager.RuningPlayUnit:FindPlayableObject(playableObjectId)
    if playableObject then
      local trans = playableObject.entity:GetTransform()
      self.oriForward = trans.forward
      self.oriPos = trans.position
      self.virtualCamera = trans:GetComponent(typeof(C_CinemachineVirtualCamera))
      local zNormalized = L_Vector3.new(self.oriForward.x, 0, self.oriForward.z):calNormalized()
      local reference = {
        x = 0,
        y = 1,
        z = 0
      }
      self.xNormalized = L_Vector3.cross(zNormalized, reference)
      if self.xNormalized.x == 0 and self.xNormalized.y == 0 and self.xNormalized.z == 0 then
        reference = {
          x = 1,
          y = 0,
          z = 0
        }
        self.xNormalized = L_Vector3.cross(zNormalized, reference)
      end
      self.xNormalized = self.xNormalized:calNormalized()
      self.yNormalized = L_Vector3.cross(self.xNormalized, zNormalized)
      self.yNormalized = self.yNormalized:calNormalized()
      self.xOffset = 0
      self.yOffset = 0
      self.cameraValid = 0 >= self.distanceLimit or L_Vector3.distance(self.oriPos, self.targetPos) < self.distanceLimit
      print("[\229\175\187\230\137\190\228\185\140\229\146\170] \229\189\147\229\137\141\230\156\186\228\189\141\232\183\157\231\166\187\239\188\154" .. L_Vector3.distance(self.oriPos, self.targetPos))
    end
    self.maxOffset = self.cameraOffsetList[self.playableObjectIndex]
    self.bind.angle = self.cameraAngleList[self.playableObjectIndex]
  end
  self.photographCamera = L_CameraManager:getCurCamController():getVirCamera()
  if self.virtualCamera then
    self.virtualCamera.enabled = true
    self:copyVirtualCamera(self.virtualCamera, self.photographCamera)
  end
end

function this:copyVirtualCamera(source, target)
  target.transform.position = source.transform.position
  target.m_Lens = source.m_Lens
  local v = source.transform.localEulerAngles.x
  local h = source.transform.localEulerAngles.y
  local body = target:GetCinemachineComponent(0)
  local aim = target:GetCinemachineComponent(1)
  if aim then
    local m_VerticalAxis = aim.m_VerticalAxis
    m_VerticalAxis.m_MinValue = v - 10
    m_VerticalAxis.m_MaxValue = v + 10
    m_VerticalAxis.Value = v
    aim.m_VerticalAxis = m_VerticalAxis
    local m_HorizontalAxis = aim.m_HorizontalAxis
    m_HorizontalAxis.m_MinValue = h - 10
    m_HorizontalAxis.m_MaxValue = h + 10
    m_HorizontalAxis.Value = h
    aim.m_HorizontalAxis = m_HorizontalAxis
  end
end

function this:bindScreenTouch(sign)
  self.onDragStartHandle = self.onDragStartHandle or L_CommonUtil.handle(self.onTouch_dragStart, self)
  self.onDragHandle = self.onDragHandle or L_CommonUtil.handle(self.onTouch_drag, self)
  self.onDragEndHandle = self.onDragEndHandle or L_CommonUtil.handle(self.onTouch_dragEnd, self)
  C_ScreenTouch.OnUI_DragStart(sign, self.onDragStartHandle)
  C_ScreenTouch.OnUI_Drag(sign, self.onDragHandle)
  C_ScreenTouch.OnUI_DragEnd(sign, self.onDragEndHandle)
end

function this:onTouch_dragStart(gesture)
  self.touchMain = gesture.go == self.bindComponents.main.gameObject
end

function this:onTouch_drag(gesture)
  if not self.touchMain then
    return
  end
  if self.virtualCamera == nil then
    return
  end
  local tempForward = self.virtualCamera.transform.forward
  self.virtualCamera.transform.eulerAngles = C_Vector3(self.virtualCamera.transform.eulerAngles.x - 360 * self.cameraRotateSpeed * gesture.deltaTime * (gesture.deltaPosition.y / C_Screen.height), self.virtualCamera.transform.eulerAngles.y + 360 * self.cameraRotateSpeed * gesture.deltaTime * (gesture.deltaPosition.x / C_Screen.width), 0)
  local angle = C_Vector3.Angle(self.oriForward, self.virtualCamera.transform.forward)
  if angle > self.bind.angle then
    self.virtualCamera.transform.forward = tempForward
  end
end

function this:onTouch_dragEnd()
  self.touchMain = nil
end

function this:getSearchTargetStates()
  local curPos = self:getCameraPos()
  if curPos == nil then
    return
  end
  if self.cameraValid == nil or not self.cameraValid then
    return false
  end
  local mainCamera = C_CameraManager.mainCamera
  local trans = mainCamera.transform
  local forward = trans.forward
  local dir = Unity.Vector3.ProjectOnPlane(self.targetPos - curPos, forward)
  local targetAngle = Unity.Vector3.SignedAngle(trans.up, dir, forward)
  self.bind.indicatorAngle = C_Vector3(0, 0, targetAngle)
  local targetDir = self.targetPos - curPos
  local angle = C_Vector3.Angle(forward, targetDir)
  local isInTarget = angle < 4.5
  local isBlock = trans:IsPointToPointBlock(self.targetPos, self.targetGo)
  return isInTarget and not isBlock
end

function this:updateTargetTip()
  self.isInTarget = self:getSearchTargetStates()
  if self.isInTarget == nil then
    return
  end
  self.bind.searchActive = self.isInTarget
  self.bind.targetAniActive = self.isInTarget
end

function this:getCameraPos()
  local camera = C_CameraManager.mainCamera
  if camera == nil then
    return
  end
  local pos = camera.transform.position
  return pos
end

function this:update()
  if self.isSearchTarget then
    self:updateTargetTip()
  end
end

return this
