#pragma once

#include <math/seadMatrix.h>
#include <math/seadQuat.h>
#include <math/seadVector.h>

namespace sead {
class Projection;
class LookAtCamera;
}  // namespace sead

namespace al {
class CameraPoser;
class Projection;
struct CameraStartInfo;
struct CameraObjectRequestInfo;
class IUseCollision;
class PlacementInfo;
}  // namespace al

namespace alCameraPoserFunction {
class CameraCollisionHitResult;

s32 getViewIndex(const al::CameraPoser*);
sead::LookAtCamera* getLookAtCamera(const al::CameraPoser*);
sead::Projection* getProjectionSead(const al::CameraPoser*);
al::Projection* getProjection(const al::CameraPoser*);
const sead::Matrix34f& getProjectionMtx(const al::CameraPoser*);
f32 getNear(const al::CameraPoser*);
f32 getFar(const al::CameraPoser*);
f32 getAspect(const al::CameraPoser*);
const sead::Vector3f& getPreCameraPos(const al::CameraPoser*);
const sead::Vector3f& getPreLookAtPos(const al::CameraPoser*);
const sead::Vector3f& getPreUpDir(const al::CameraPoser*);
f32 getPreFovyDegree(const al::CameraPoser*);
f32 getPreFovyRadian(const al::CameraPoser*);
bool isPrePriorityDemo(const al::CameraStartInfo&);
bool isPrePriorityDemo2(const al::CameraStartInfo&);
bool isPrePriorityDemoTalk(const al::CameraStartInfo&);
bool isPrePriorityDemoAll(const al::CameraStartInfo&);
bool isPrePriorityEntranceAll(const al::CameraStartInfo&);
bool isPrePriorityPlayer(const al::CameraStartInfo&);
bool isEqualPreCameraName(const al::CameraStartInfo&, const char*);
bool isPreCameraFixAbsolute(const al::CameraStartInfo&);
bool isInvalidCollidePreCamera(const al::CameraStartInfo&);
bool isInvalidKeepPreCameraDistance(const al::CameraStartInfo&);
bool isInvalidKeepPreCameraDistanceIfNoCollide(const al::CameraStartInfo&);
bool isValidResetPreCameraPose(const al::CameraStartInfo&);
bool isValidKeepPreSelfCameraPose(const al::CameraStartInfo&);
f32 getPreCameraSwingAngleH(const al::CameraStartInfo&);
f32 getPreCameraSwingAngleV(const al::CameraStartInfo&);
f32 getPreCameraMaxSwingAngleH(const al::CameraStartInfo&);
f32 getPreCameraMaxSwingAngleV(const al::CameraStartInfo&);
bool isExistAreaAngleH(const al::CameraStartInfo&);
bool isExistAreaAngleV(const al::CameraStartInfo&);
f32 getAreaAngleH(const al::CameraStartInfo&);
f32 getAreaAngleV(const al::CameraStartInfo&);
bool isExistNextPoseByPreCamera(const al::CameraStartInfo&);
f32 getNextAngleHByPreCamera(const al::CameraStartInfo&);
f32 getNextAngleVByPreCamera(const al::CameraStartInfo&);
void calcCameraPose(sead::Quatf*, const al::CameraPoser*);
void calcLookDir(sead::Vector3f*, const al::CameraPoser*);
void calcCameraDir(sead::Vector3f*, const al::CameraPoser*);
bool calcCameraDirH(sead::Vector3f*, const al::CameraPoser*);
void calcLookDirH(sead::Vector3f*, const al::CameraPoser*);
void calcSideDir(sead::Vector3f*, const al::CameraPoser*);
void calcPreCameraDir(sead::Vector3f*, const al::CameraPoser*);
void calcPreCameraDirH(sead::Vector3f*, const al::CameraPoser*);
void calcPreLookDir(sead::Vector3f*, const al::CameraPoser*);
void calcPreLookDirH(sead::Vector3f*, const al::CameraPoser*);
void calcPreCameraAngleH(const al::CameraPoser*);
void calcPreCameraAngleV(const al::CameraPoser*);
void setLookAtPosToTarget(al::CameraPoser*);
void calcTargetTrans(sead::Vector3f*, const al::CameraPoser*);
void setLookAtPosToTargetAddOffset(al::CameraPoser*, const sead::Vector3f&);
void setCameraPosToTarget(al::CameraPoser*);
void setCameraPosToTargetAddOffset(al::CameraPoser*, const sead::Vector3f&);
void calcTargetTransWithOffset(sead::Vector3f*, const al::CameraPoser*);
void calcTargetVelocity(sead::Vector3f*, const al::CameraPoser*);
void calcTargetVelocityH(sead::Vector3f*, const al::CameraPoser*);
void calcTargetUp(sead::Vector3f*, const al::CameraPoser*);
f32 calcTargetSpeedV(const al::CameraPoser*);
void calcTargetPose(sead::Quatf*, const al::CameraPoser*);
void calcTargetFront(sead::Vector3f*, const al::CameraPoser*);
void calcTargetSide(sead::Vector3f*, const al::CameraPoser*);
void calcTargetGravity(sead::Vector3f*, const al::CameraPoser*);
f32 calcTargetSpeedH(const al::CameraPoser*);
f32 calcTargetJumpSpeed(const al::CameraPoser*);
f32 calcTargetFallSpeed(const al::CameraPoser*);
bool isChangeTarget(const al::CameraPoser*);
bool tryGetTargetRequestDistance(f32*, const al::CameraPoser*);
bool tryGetBossDistanceCurve(const al::CameraPoser*);
bool tryGetEquipmentDistanceCurve(const al::CameraPoser*);
bool isExistCollisionUnderTarget(const al::CameraPoser*);
const sead::Vector3f& getUnderTargetCollisionPos(const al::CameraPoser*);
const sead::Vector3f& getUnderTargetCollisionNormal(const al::CameraPoser*);
bool isExistSlopeCollisionUnderTarget(const al::CameraPoser*);
bool isExistWallCollisionUnderTarget(const al::CameraPoser*);
bool tryCalcSlopeCollisionDownFrontDirH(sead::Vector3f*, const al::CameraPoser*);
void getSlopeCollisionUpSpeed(const al::CameraPoser*);
void getSlopeCollisionDownSpeed(const al::CameraPoser*);
bool isExistSubTarget(const al::CameraPoser*);
void checkValidTurnToSubTarget(const al::CameraPoser*);
void calcSubTargetBack(sead::Vector3f*, const al::CameraPoser*);
void calcSubTargetTrans(sead::Vector3f*, const al::CameraPoser*);
bool isChangeSubTarget(const al::CameraPoser*);
void calcSubTargetFront(sead::Vector3f*, const al::CameraPoser*);
void getSubTargetRequestDistance(const al::CameraPoser*);
void getSubTargetTurnSpeedRate1(const al::CameraPoser*);
void getSubTargetTurnSpeedRate2(const al::CameraPoser*);
void getSubTargetTurnRestartStep(const al::CameraPoser*);
bool tryCalcSubTargetTurnBrakeDistanceRate(f32*, const al::CameraPoser*);
bool isValidSubTargetTurnV(const al::CameraPoser*);
bool isValidSubTargetResetAfterTurnV(const al::CameraPoser*);
void clampAngleSubTargetTurnRangeV(f32*, const al::CameraPoser*);
void initCameraVerticalAbsorber(al::CameraPoser*);
void initCameraVerticalAbsorberNoCameraPosAbsorb(al::CameraPoser*);
void getCameraVerticalAbsorbPosUp(const al::CameraPoser*);
void getCameraVerticalAbsorbPosDown(const al::CameraPoser*);
void liberateVerticalAbsorb(al::CameraPoser*);
void stopUpdateVerticalAbsorb(al::CameraPoser*);
void stopUpdateVerticalAbsorbForSnapShotMode(al::CameraPoser*, const sead::Vector3f&);
void restartUpdateVerticalAbsorb(al::CameraPoser*);
void validateVerticalAbsorbKeepInFrame(al::CameraPoser*);
void invalidateVerticalAbsorbKeepInFrame(al::CameraPoser*);
void setVerticalAbsorbKeepInFrameScreenOffsetUp(al::CameraPoser*, f32);
void setVerticalAbsorbKeepInFrameScreenOffsetDown(al::CameraPoser*, f32);
void initCameraArrowCollider(al::CameraPoser*);
void initCameraArrowColliderWithoutThroughPassCollision(al::CameraPoser*);
void initCameraMoveLimit(al::CameraPoser*);
void initCameraAngleCtrl(al::CameraPoser*);
void initCameraAngleCtrlWithRelativeH(al::CameraPoser*);
void initCameraDefaultAngleRangeV(al::CameraPoser*, f32, f32);
void setCameraStartAngleV(al::CameraPoser*, f32);
void setCameraAngleV(al::CameraPoser*, f32);
void getCameraAngleH(const al::CameraPoser*);
void getCameraAngleV(const al::CameraPoser*);
void initAngleSwing(al::CameraPoser*);
bool isValidAngleSwing(const al::CameraPoser*);
void initCameraOffsetCtrlPreset(al::CameraPoser*);
void getOffset(const al::CameraPoser*);
void initGyroCameraCtrl(al::CameraPoser*);
void resetGyro(al::CameraPoser*);
void calcCameraGyroPose(const al::CameraPoser*, sead::Vector3f*, sead::Vector3f*, sead::Vector3f*);
void getGyroFront(al::CameraPoser*);
void getGyroAngleV(al::CameraPoser*);
void getGyroAngleH(al::CameraPoser*);
void setGyroLimitAngleV(al::CameraPoser*, f32, f32);
void setGyroSensitivity(al::CameraPoser*, f32, f32);
void reduceGyroSencitivity(al::CameraPoser*);
void stopUpdateGyro(al::CameraPoser*);
void restartUpdateGyro(al::CameraPoser*);
bool isStopUpdateGyro(const al::CameraPoser*);
bool isTargetCollideGround(const al::CameraPoser*);
bool isTargetInWater(const al::CameraPoser*);
bool isTargetInMoonGravity(const al::CameraPoser*);
bool isTargetClimbPole(const al::CameraPoser*);
bool isTargetGrabCeil(const al::CameraPoser*);
bool isTargetInvalidMoveByInput(const al::CameraPoser*);
bool isTargetEnableEndAfterInterpole(const al::CameraPoser*);
bool isTargetWallCatch(const al::CameraPoser*);
bool isSnapShotMode(const al::CameraPoser*);
void initSnapShotCameraCtrl(al::CameraPoser*);
void initSnapShotCameraCtrlZoomAutoReset(al::CameraPoser*);
void initSnapShotCameraCtrlZoomRollMove(al::CameraPoser*);
void validateSnapShotCameraLookAtOffset(al::CameraPoser*);
void validateSnapShotCameraZoomFovy(al::CameraPoser*);
void validateSnapShotCameraRoll(al::CameraPoser*);
void updateSnapShotCameraCtrl(al::CameraPoser*);
void startResetSnapShotCameraCtrl(al::CameraPoser*, s32);
void setSnapShotMaxZoomOutFovyDegree(al::CameraPoser*, f32);
void getSnapShotRollDegree(const al::CameraPoser*);
void getSnapShotLookAtOffset(const al::CameraPoser*);
bool isOffVerticalAbsorb(const al::CameraPoser*);
void onVerticalAbsorb(al::CameraPoser*);
void offVerticalAbsorb(al::CameraPoser*);
void invalidateCameraBlur(al::CameraPoser*);
bool isRequestStopVerticalAbsorb(const al::CameraObjectRequestInfo&);
bool isRequestResetPosition(const al::CameraObjectRequestInfo&);
bool isRequestResetAngleV(const al::CameraObjectRequestInfo&);
bool isRequestDownToDefaultAngleBySpeed(const al::CameraObjectRequestInfo&);
bool isRequestUpToTargetAngleBySpeed(const al::CameraObjectRequestInfo&);
void getRequestTargetAngleV(const al::CameraObjectRequestInfo&);
void getRequestAngleSpeed(const al::CameraObjectRequestInfo&);
bool isRequestMoveDownAngleV(const al::CameraObjectRequestInfo&);
bool isRequestSetAngleV(const al::CameraObjectRequestInfo&);
void getRequestAngleV(const al::CameraObjectRequestInfo&);
bool isInvalidCollider(const al::CameraPoser*);
void validateCollider(al::CameraPoser*);
void invalidateCollider(al::CameraPoser*);
void validateCtrlSubjective(al::CameraPoser*);
void invalidateChangeSubjective(al::CameraPoser*);
void invalidateKeepDistanceNextCamera(al::CameraPoser*);
void invalidateKeepDistanceNextCameraIfNoCollide(al::CameraPoser*);
void invalidatePreCameraEndAfterInterpole(al::CameraPoser*);
bool isInvalidPreCameraEndAfterInterpole(const al::CameraPoser*);
bool isSceneCameraFirstCalc(const al::CameraPoser*);
bool isActiveInterpole(const al::CameraPoser*);
bool isInvalidEndEntranceCamera(const al::CameraPoser*);
bool isPause(const al::CameraPoser*);
bool checkFirstCameraCollisionArrow(sead::Vector3f*, sead::Vector3f*, const al::IUseCollision*,
                                    const sead::Vector3f&, const sead::Vector3f&);
bool checkFirstCameraCollisionArrow(CameraCollisionHitResult*, const al::IUseCollision*,
                                    const sead::Vector3f&, const sead::Vector3f&);
bool checkFirstCameraCollisionArrowOnlyCeiling(sead::Vector3f*, sead::Vector3f*,
                                               const al::IUseCollision*, const sead::Vector3f&,
                                               const sead::Vector3f&);
void checkCameraCollisionMoveSphere(sead::Vector3f*, const al::IUseCollision*,
                                    const sead::Vector3f&, const sead::Vector3f&, f32);
f32 calcZoneRotateAngleH(f32, const al::CameraPoser*);
f32 calcZoneRotateAngleH(f32, const sead::Matrix34f&);
f32 calcZoneInvRotateAngleH(f32, const sead::Matrix34f&);
void multVecZone(sead::Vector3f*, const sead::Vector3f&, const al::CameraPoser*);
void multVecInvZone(sead::Vector3f*, const sead::Vector3f&, const al::CameraPoser*);
void rotateVecZone(sead::Vector3f*, const sead::Vector3f&, const al::CameraPoser*);
void calcOffsetCameraKeepInFrameV(sead::Vector3f*, sead::LookAtCamera*, const sead::Vector3f&,
                                  const al::CameraPoser*, f32, f32);
void makeCameraKeepInFrameV(sead::LookAtCamera*, const sead::Vector3f&, const al::CameraPoser*, f32,
                            f32);
void initCameraRail(al::CameraPoser*, const al::PlacementInfo&, const char*);
bool tryGetCameraRailArg(f32*, const al::PlacementInfo&, const char*, const char*);
// void getCameraRailPointObjId(al::CameraPoser const*, s32);
bool tryFindNearestLimitRailKeeper(const al::CameraPoser*, const sead::Vector3f&);
void calcCameraRotateStick(sead::Vector2f*, const al::CameraPoser*);
f32 calcCameraRotateStickH(const al::CameraPoser*);
f32 calcCameraRotateStickV(const al::CameraPoser*);
f32 calcCameraRotateStickPower(const al::CameraPoser*);
s32 getStickSensitivityLevel(const al::CameraPoser*);
f32 getStickSensitivityScale(const al::CameraPoser*);
bool isValidGyro(const al::CameraPoser*);
s32 getGyroSensitivityLevel(const al::CameraPoser*);
f32 getGyroSensitivityScale(const al::CameraPoser*);
bool isTriggerCameraResetRotate(const al::CameraPoser*);
bool isHoldCameraZoom(const al::CameraPoser*);
bool isHoldCameraSnapShotZoomIn(const al::CameraPoser*);
bool isHoldCameraSnapShotZoomOut(const al::CameraPoser*);
bool isHoldCameraSnapShotRollLeft(const al::CameraPoser*);
bool isHoldCameraSnapShotRollRight(const al::CameraPoser*);
bool tryCalcCameraSnapShotMoveStick(sead::Vector2f*, const al::CameraPoser*);
bool isPlayerTypeFlyer(const al::CameraPoser*);
bool isPlayerTypeHighSpeedMove(const al::CameraPoser*);
bool isPlayerTypeHighJump(const al::CameraPoser*);
bool isPlayerTypeNotTouchGround(const al::CameraPoser*);
bool isOnRideObj(const al::CameraPoser*);
}  // namespace alCameraPoserFunction
