﻿#pragma once

#include "Common.h"
#include "ImageManager.h"
#include "SoundManager.h"
#include "Stage.h"

// プレイヤー画像のどの動きを再生するかを表す
enum class PlayerAnimation
{
    Idle,
    Run,
    Jump,
    Fall
};

// プレイヤーの位置、大きさ、速度、接地状態
struct Player
{
    int x;
    int y;
    int width;
    int height;
    float vx;
    float vy;
    float remainderX;
    float remainderY;
    bool onGround;
    PlayerAnimation animation;
    int animationFrame;
    int animationTimer;
    bool facingRight;
    int coyoteFrames;
    int jumpBufferFrames;
};

enum class EnemyState
{
    Idle,
    Patrol,
    Chase,
    Defeated
};

// CSVから複数配置する敵の位置、大きさ、速度、移動範囲、行動状態
struct Enemy
{
    int x;
    int y;
    int width;
    int height;
    float vx;
    float vy;
    float remainderX;
    float remainderY;
    int minX;
    int maxX;
    bool isActive;
    EnemyState state;
    int stateTimer;
};


// ゲーム全体が現在どの場面にいるかを表す
enum GameState
{
    Title,
    Playing,
    GameClear,
    GameOver
};

// 入力、ゲーム状態、キャラクター、描画の流れを管理する
class Game
{
public:
    bool Initialize();
    void MainLoop();

private:
    // プレイ開始時に必要な値を初期状態へ戻す
    void StartPlay();
    void ChangeGameState(GameState nextState);
    void ResetPlay();
    void ResetPlayer();
    void ResetEnemies();

    // 現在のゲーム状態に応じた更新処理
    void Update();
    void UpdateTitle();
    void UpdatePlaying();
    void UpdateResult();
    void UpdatePlayerInput();
    void UpdatePlayerPhysics();
    void UpdatePlayerAnimation();
    void UpdateEnemies();
    void UpdateEnemyBehavior(Enemy& enemy);
    void UpdateEnemyPhysics(Enemy& enemy);
    void ChangeEnemyState(Enemy& enemy, EnemyState nextState);
    void MoveEnemyHorizontal(Enemy& enemy);
    void MoveEnemyVertical(Enemy& enemy);
    void UpdateCamera();
    void UpdateDebugToggle();

    // タイルと重ならないよう、横方向と縦方向を別々に移動する
    void MoveHorizontal(float move);
    void MoveVertical(float move);

    // 当たり判定用と画像描画用の矩形は別に計算する
    Rect PlayerRect() const;
    Rect EnemyRect(const Enemy& enemy) const;
    Rect PlayerImageRect() const;
    Rect EnemyImageRect(const Enemy& enemy) const;
    int PlayerFrameIndex() const;

    // 現在のゲーム状態に応じた描画処理
    void Draw();
    void DrawBackground() const;
    void DrawTitle() const;
    void DrawPlaying() const;
    void DrawResult() const;
    void DrawPlayer() const;
    void DrawEnemies() const;
    void DrawHud() const;
    void DrawDebug() const;

private:
    // 画面サイズ
    static const int screenWidth = 640;
    static const int screenHeight = 480;

    // プレイヤーの操作感を決める物理パラメーター
    static constexpr float accel = 0.35f;
    static constexpr float maxSpeed = 4.5f;
    static constexpr float friction = 0.25f;
    static constexpr float riseGravity = 0.45f;
    static constexpr float fallGravity = 0.75f;
    static constexpr float maxFallSpeed = 12.0f;

    // Player.pngは同じ大きさのフレームを横8枚に並べる
    static const int playerFrameCount = 8;

    static const int playerDrawWidth = 32;
    static const int playerDrawHeight = 48;
    static constexpr float jumpPower = -11.0f;
    static constexpr float jumpCutMultiplier = 0.5f;
    static const int coyoteFrameLimit = 6;
    static const int jumpBufferFrameLimit = 6;
    static constexpr float enemyGravity = 0.55f;
    static constexpr float enemyMaxFallSpeed = 12.0f;
    static const int enemyIdleFrames = 60;
    static constexpr float enemyPatrolSpeed = 2.0f;
    static constexpr float enemyChaseSpeed = 3.0f;
    static const int enemyChaseStartDistance = 180;
    static const int enemyChaseEndDistance = 260;
    static constexpr float enemyDefeatedJumpPower = -6.0f;

    // ゲーム中に保持するデータ
    ImageManager images;
    SoundManager sounds;
    Stage stage;
    Player player = {};
    static const int maxEnemyCount = Stage::maxEnemySpawns;
    Enemy enemies[maxEnemyCount] = {};
    int enemyCount = 0;
    int cameraX = 0;
    GameState gameState = Title;
    bool debugVisible = false;
    bool previousF1 = false;
    bool previousZ = false;
};
