#pragma once

#include <math/seadQuat.h>

#include "Library/LiveActor/LiveActorGroup.h"
#include "Library/Message/LanguageUtil.h"
#include "Library/Scene/Scene.h"

namespace al {
class LayoutActor;
class SimpleLayoutAppearWaitEnd;
class ParabolicPath;
class WipeSimple;
class WipeHolder;
class WindowConfirm;
class SimpleAudioUser;
class DemoSyncedEventKeeper;
class LayoutTextureRenderer;
class ChromakeyDrawer;
class HtmlViewer;
class CameraTicket;
}  // namespace al

class Shine;
class GameDataHolderAccessor;
class GameDataHolder;
class MapLayout;
class ProjectItemDirector;
class PlayerActorHakoniwa;
class ProjectDemoDirector;
class StageSceneLayout;
class TimeBalloonNpc;
class TimeBalloonDirector;
class TimeBalloonSequenceInfo;
class CollectBgmPlayer;
class CollectBgmRegister;
class BgmAnimeSyncDirector;
class NpcEventDirector;
class ScenarioStartCameraHolder;
class ControllerGuideSnapShotCtrl;
class InputSeparator;
class MiniGameMenu;
class Pyramid;
class SceneAudioSystemPauseController;
class DemoSoundSynchronizer;
class StageSceneStateWorldMap;
class StageSceneStateShop;
class StageSceneStateSnapShot;
class StageSceneStateGetShine;
class StageSceneStateGetShineMain;
class StageSceneStateGetShineGrand;
class StageSceneStateCollectBgm;
class StageSceneStateCollectionList;
class StageSceneStateMiniGameRanking;
class StageSceneStatePauseMenu;
class StageSceneStateCloset;
class StageSceneStateSkipDemo;
class StageSceneStateCheckpointWarp;
class StageSceneStateCarryMeat;
class StageSceneStateMiss;
class StageSceneStateYukimaruRace;
class StageSceneStateYukimaruRaceTutorial;
class StageSceneStateRaceManRace;
class StageSceneStateRadicon;
class StageSceneStateScenarioCamera;
class StageSceneStateRecoverLife;
class StageSceneStateGetShineMainSandWorld;
class StageSceneStateWarp;
class ProjectSeNamedList;
class ProjectNfpDirector;
class PlayGuideSkip;
class CinemaCaption;
class KoopaLv1;
class StageSceneStateWorldIntroCamera;
class StageSceneStateTimeBalloon;
class StageSceneStateTitleLogo;
class StageSceneStateTalk;
class LocationNameCtrl;
class ShoppingWatcher;
class CollectionList;
class OpeningStageStartDemo;
class HelpAmiiboDirector;

class StageScene : public al::Scene {
public:
    StageScene();
    ~StageScene() override;

    void init(const al::SceneInitInfo& info) override;
    void stopCollectBgm();
    bool tryChangeDemo();
    void appear() override;
    void control() override;
    bool isIgnoreAddPlayTime() const;
    void kill() override;
    bool isGetGrandShineAndEnableWipeClose() const;
    bool isGetGrandShine() const;
    bool isVeilEnd() const;
    bool isE3End() const;
    bool isDefeatKoopaLv1() const;
    bool isMissEnd() const;
    bool isHackEnd() const;
    bool isLoadData() const;
    bool isModeSelectEnd() const;
    bool isNewGame() const;
    bool isChangeLanguage() const;
    alLanguage getLanguage() const;
    bool isEnableSave() const;
    bool isPause() const;
    void drawMain() const override;
    bool isEnableToDrawOddSpace() const;
    bool updatePlay();
    void endDemoAndChangeNerve();
    void updateKitListPostAndChangeNextNerve(const al::Nerve*);
    void exeStartStageBgm();
    void exePlay();
    void updateStageSceneLayoutForKoopaHack();
    bool tryChangeSnapShot();
    bool tryStartWarp();
    bool tryChangePause();
    bool tryChangeList();
    void updateStageInfoLayout();
    void endPlay();
    void exeAmiibo();
    void exeMiss();
    void exeSnapShot();
    void exePause();
    void exeDemoStageStart();
    void exeDemoStageStartCapManHeroTalk();
    void exeDemoNormal();
    void tryAppearDemoLayout();
    void exeDemoNormalBazookaElectric();
    void exeDemoWithPlayer();
    void exeSkipDemo();
    void exeDemoTalk();
    bool tryUpdateAllForFirst();
    void exeDemoWithPlayerUseCoin();
    void exeDemoCountCoin();
    void exeDemoHackStart();
    void exeDemoHackStartFirst();
    void exeDemoCarryMeat();
    void exeDemoTitleLogo();
    void exeDemoShineGet();
    void exeDemoShineMainGet();
    void exeWaitStartWarpForSession();
    void exeDemoShineGrandGet();
    void exeDemoDamageStopPlayer();
    void exeDemoGetLifeMaxUpItem();
    void exeDemoSceneStartPlayerWalk();
    void exeAppearFromWorldWarpHole();
    void exeWaitWarpToCheckpoint();
    void exeWarpToCheckpoint();
    void exeArriveAtCheckpoint();
    void exeWarp();
    void exeDemoWorldIntroCamera();
    void exeDemoPlayerDown();
    void exeDemoScenarioCamera();
    void exeDemoAppearFromHome();
    void exeDemoReturnToHome();
    void exeDemoRiseMapParts();
    void exeDemoRisePyramid();
    void exeDemoShineChipComplete();
    void exeRaceManRace();
    void exeRaceYukimaru();
    void exeRaceYukimaruTutorial();
    void exeRadicon();
    void exeCollectionList();
    void exeShop();
    void exeCloset();
    void exeCollectBgm();
    void exeMiniGameRanking();
    void exeTimeBalloon();
    bool isOpenEndWorldMapWipe() const;

private:
    sead::FixedSafeString<64> mStageName;
    s32 mScenarioNo = 0;
    StageSceneStateWorldMap* mStateWorldMap = nullptr;
    StageSceneStateShop* mStateShop = nullptr;
    StageSceneStateSnapShot* mStateSnapShot = nullptr;
    StageSceneStateGetShine* mStateGetShine = nullptr;
    StageSceneStateGetShineMain* mStateGetShineMain = nullptr;
    StageSceneStateGetShineGrand* mStateGetShineGrand = nullptr;
    StageSceneStateCollectBgm* mStateCollectBgm = nullptr;
    StageSceneStateCollectionList* mStateCollectionList = nullptr;
    StageSceneStateMiniGameRanking* mStateMiniGameRanking = nullptr;
    StageSceneStatePauseMenu* mStagePauseMenu = nullptr;
    StageSceneStateCloset* mStateCloset = nullptr;
    StageSceneStateSkipDemo* mStateSkipDemo = nullptr;
    StageSceneStateCheckpointWarp* mStateCheckpointWarp = nullptr;
    StageSceneStateCarryMeat* mStateCarryMeat = nullptr;
    StageSceneStateTimeBalloon* mStateTimeBalloon = nullptr;
    StageSceneStateTitleLogo* mStateTitleLogo = nullptr;
    StageSceneStateMiss* mStateMiss = nullptr;
    StageSceneStateYukimaruRace* mStateYukimaruRace = nullptr;
    StageSceneStateYukimaruRaceTutorial* mStateYukimaruRaceTutorial = nullptr;
    StageSceneStateRaceManRace* mStateRaceManRace = nullptr;
    StageSceneStateRadicon* mStateRadicon = nullptr;
    StageSceneStateScenarioCamera* mStateScenarioCamera = nullptr;
    StageSceneStateRecoverLife* mStateRecoverLife = nullptr;
    StageSceneStateGetShineMainSandWorld* mStateGetShineMainSandWorld = nullptr;
    StageSceneStateTalk* mStateTalk = nullptr;
    StageSceneStateWarp* mStateWarp = nullptr;
    StageSceneStateWorldIntroCamera* mStateWorldIntroCamera = nullptr;
    ScenarioStartCameraHolder* mScenarioStartCameraHolder = nullptr;
    sead::FixedSafeString<64> mCostumeName;
    sead::FixedSafeString<64> mCapTypeName;
    void* _2c8 = nullptr;
    GameDataHolder* mGameDataHolder = nullptr;
    al::PlacementInfo* mPlacementInfo = nullptr;
    al::LayoutTextureRenderer* mLayoutTextureRenderer = nullptr;
    PlayGuideSkip* mPlayGuideSkip = nullptr;
    CinemaCaption* mCinemaCaption = nullptr;
    StageSceneLayout* mSceneLayout = nullptr;
    bool mIsPlayerHackFukankun = false;
    bool mIsKoopaHackDemo = false;
    al::SimpleLayoutAppearWaitEnd* mScenarioStartLayout = nullptr;
    al::SimpleLayoutAppearWaitEnd* mWorldStartCountryLayout = nullptr;
    al::SimpleLayoutAppearWaitEnd* mWorldStartRegionLayout = nullptr;
    ControllerGuideSnapShotCtrl* mControllerGuideSnapshotCtrl = nullptr;
    InputSeparator* mInputSeparator = nullptr;
    al::WipeSimple* mWipeSimple = nullptr;
    al::WipeHolder* mWipeHolder = nullptr;
    LocationNameCtrl* mLocationNameCtrl = nullptr;
    al::WindowConfirm* mWindowConfirm = nullptr;
    MiniGameMenu* mMiniGameMenu = nullptr;
    bool mIsExistShineOrCoinCollectInStage = false;
    char _359[7];
    bool _360 = false;
    void* _368 = nullptr;
    MapLayout* mMapLayout = nullptr;
    al::SimpleLayoutAppearWaitEnd* mPauseMenu = nullptr;
    al::DeriveActorGroup<ShoppingWatcher>* mShoppingWatcherGroup = nullptr;
    CollectionList* mCollectionList = nullptr;
    KoopaLv1* mKoopaLv1 = nullptr;
    TimeBalloonNpc* mTimeBalloonNpc = nullptr;
    ProjectItemDirector* mProjectItemDirector = nullptr;
    Pyramid* mPyramid = nullptr;
    OpeningStageStartDemo* mOpeningStageStartDemo = nullptr;
    al::Nerve* mCurrentNerve = nullptr;
    SceneAudioSystemPauseController* mAudioSystemPauseController = nullptr;
    DemoSoundSynchronizer* mDemoSoundSynchronizer = nullptr;
    al::SimpleAudioUser* mStageStartAtmosSe = nullptr;
    al::SimpleAudioUser* mSePlayArea = nullptr;
    al::SimpleAudioUser* mSnapShotCameraCtrl = nullptr;
    ProjectSeNamedList* mSeNamedList = nullptr;
    void* _3f0 = nullptr;
    TimeBalloonDirector* mTimeBalloonDirector = nullptr;
    TimeBalloonSequenceInfo* mTimeBalloonSequenceInfo = nullptr;
    void* _408 = nullptr;
    al::CameraTicket* mCheckpointWarpArriveCamera = nullptr;
    sead::Vector3f mCheckpointWarpTargetPos = {0.0f, 0.0f, 0.0f};
    sead::Vector3f mCheckpointWarpParabolicPathPos = {0.0f, 0.0f, 0.0f};
    sead::Vector3f mCheckpointWarpParabolicPathEnd = {0.0f, 0.0f, 0.0f};
    al::LiveActor* mCheckpointWarpCapActor = nullptr;
    al::ParabolicPath* mCheckpointWarpParabolicPath = nullptr;
    al::LiveActor* mDemoShine = nullptr;
    al::LiveActor* mDemoDotShine = nullptr;
    void* _460 = nullptr;
    CollectBgmPlayer* mCollectBgmPlayer = nullptr;
    CollectBgmRegister* mCollectBgmRegister = nullptr;
    BgmAnimeSyncDirector* mBgmAnimeSyncDirector = nullptr;
    al::DemoSyncedEventKeeper* mDemoSyncedEventKeeper = nullptr;
    const char* mActiveDemoName = nullptr;
    s32 mDemoSynchronizerTimer = 0;
    bool _494 = false;
    bool mIsUpdateKitAndGraphics = false;
    bool _496 = false;
    NpcEventDirector* mNpcEventDirector = nullptr;
    al::ChromakeyDrawer* mChromakeyDrawer = nullptr;
    al::HtmlViewer* mHtmlViewer = nullptr;
    ProjectNfpDirector* mProjectNfpDirector = nullptr;
    HelpAmiiboDirector* mHelpAmiiboDirector = nullptr;
};

static_assert(sizeof(StageScene) == 0x4C0);

namespace rs {
void tryStartRaceStage(al::Scene*, GameDataHolder*);
bool updateNormalState(al::Scene*);
void updateEffectSystemEnv(al::Scene*);
bool updateNormalStateExcludeGraphics(al::Scene*);
bool updateBirdCarryMeat(al::Scene*);
void updateKitListExcludePlayer(al::Scene*);
void updateKitListExcludeCamera(al::Scene*);
void updateKitListExcludeCameraDemoChangeWorld(al::Scene*);
void updateKitListPlayerGroupNormal(al::Scene*);
void updateKitListDemoPlayerNoPauseEffect(al::Scene*);
void updateKitListDemoPlayerWithPauseEffect(al::Scene*);
void updateKitListDemoPlayerWithPauseEffectAndCalcAtEndClip(al::Scene*);
void updateKitListDemoNormalNoPauseEffect(al::Scene*);
void updateKitListDemoNormalWithPauseEffect(al::Scene*);
void updateKitListDemoCapWorldOpeninglWithPauseEffect(al::Scene*);
void updateKitListLayout(al::Scene*);
void updateKitListPostNoViewRenderer(al::Scene*);
void updateKitListLayoutIgnorePause(al::Scene*);
void updateKitListLayoutOnlyLayoutScene(al::Scene*);
void updateKitListPostWithPauseNormalEffectAndPlayerEffect(al::Scene*);
void updateKitListPostSnapShot(al::Scene*);
void setScenarioName(al::LayoutActor*, const al::Scene*);
void startTalkMsgTimeBalloonLayout(const al::Scene*);
void endPlayTalkMsgTimeBalloonLayout(const al::Scene*);
void endForceTalkMsgTimeBalloonLayout(const al::Scene*);
void changeDemoCommonProc(al::Scene*, ProjectItemDirector*);
void endDemoCommonProc(al::Scene*, ProjectItemDirector*);
void endDemoNormalShineGet(al::Scene*, ProjectItemDirector*);
bool tryOpenMap(al::IUseNerve*, const al::Scene*, const MapLayout*, const al::Nerve*);
bool tryChangeNextStage(GameDataHolder*, al::Scene*);
al::LiveActor* getPlayerActor(const al::Scene*);
void registerGraphicsPreset(const al::Scene*, const char*, const char*, const char*, bool);
void requestGraphicsPreset(const al::Scene*, const char*, const sead::Vector3f&);
void requestGraphicsCubeMap(const al::Scene*, const char*, const char*);
void requestGraphicsPresetAndCubeMap(const al::Scene*, const char*, const char*, const char*);
void requestGraphicsPresetAndCubeMap(const al::Scene*, const char*, const char*, const char*,
                                     const sead::Vector3f&);
void requestGraphicsPresetAndCubeMapFixedAngle(const al::Scene*, const char*, const char*,
                                               const char*);
void registerGraphicsPresetWorldMap(const al::Scene*);
void registerGraphicsPresetShop(const al::Scene*);
void registerGraphicsPresetMoonGet(const al::Scene*);
void registerGraphicsPresetCloset(const al::Scene*);
void registerGraphicsPresetPause(const al::Scene*);
void requestGraphicsPresetAndCubeMapWorldMap(const al::Scene*);
void requestGraphicsPresetAndCubeMapShop(const al::Scene*);
void requestGraphicsPresetAndCubeMapShopNoFixedAngle(const al::Scene*);
void requestGraphicsPresetAndCubeMapMoonGet(const al::Scene*);
void requestGraphicsPresetAndCubeMapMoonGetNoFixedAngle(const al::Scene*);
void requestGraphicsPresetAndCubeMapCloset(const al::Scene*);
void requestGraphicsPresetAndCubeMapClosetNoFixedAngle(const al::Scene*);
void requestGraphicsPresetAndCubeMapPause(const al::Scene*);
void requestGraphicsPresetAndCubeMapPauseNoFixedAngle(const al::Scene*);
void calcQuatPoseCheckpointWarpCap(sead::Quatf*, const sead::Vector3f&, const al::IUseCamera*);
ProjectDemoDirector* getDemoDirector(const al::Scene*);
Shine* getDemoShineActor(const al::Scene*);
bool isExistDemoShine(const al::Scene*);
}  // namespace rs
