/**
 * @file Breakout.h
 * @brief Breakout arcade game for Tactility
 */
#pragma once

#include <tt_app.h>
#include <lvgl.h>
#include <TactilityCpp/App.h>

class SfxEngine;

enum class GameState { Ready, Playing, Paused, GameOver };
enum class BrickType : uint8_t { Normal, Silver, Gold };
enum class PowerUpType : uint8_t { Laser, Extend, Catch, Slow, BreakOut, Split, ExtraLife };

static constexpr int TICK_MS = 25;
static constexpr int MAX_COLS = 12;
static constexpr int MAX_ROWS = 5;
static constexpr int MAX_BRICKS = MAX_COLS * MAX_ROWS;
static constexpr int INITIAL_LIVES = 10;
static constexpr int MAX_CAPSULES = 4;
static constexpr int MAX_BALLS = 3;
static constexpr int MAX_LASERS = 2;

// Per-color scoring (Purple=50 through Yellow=120)
static constexpr int COLOR_SCORES[] = { 50, 60, 70, 80, 90, 100, 110, 120 };

struct Capsule {
    float x, y;
    PowerUpType type;
    bool active;
};

struct BallState {
    float x, y, vx, vy;
    bool active;
    lv_obj_t* obj;
};

struct Laser {
    float x, y;
    bool active;
    lv_obj_t* obj;
};

class Breakout final : public App {

private:
    // UI pointers (nulled in onHide)
    lv_obj_t* gameArea = nullptr;
    lv_obj_t* paddle = nullptr;
    lv_obj_t* bricks[MAX_BRICKS] = {};
    lv_obj_t* scoreLabel = nullptr;
    lv_obj_t* livesLabel = nullptr;
    lv_obj_t* messageLabel = nullptr;
    lv_timer_t* gameTimer = nullptr;
    lv_obj_t* soundBtnIcon = nullptr;

    // Capsule UI
    lv_obj_t* capsuleObjs[MAX_CAPSULES] = {};
    lv_obj_t* capsuleLabels[MAX_CAPSULES] = {};

    // Laser UI
    Laser lasers[MAX_LASERS] = {};

    // BreakOut exit
    lv_obj_t* exitIndicator = nullptr;

    // Sfx
    SfxEngine* sfxEngine = nullptr;

    // Game state (persists across hide/show)
    GameState state = GameState::Ready;
    int score = 0;
    int lives = INITIAL_LIVES;
    int level = 1;
    int bricksRemaining = 0;
    int destroyedCount = 0;
    bool brickAlive[MAX_BRICKS] = {};
    BrickType brickType[MAX_BRICKS] = {};
    int brickHits[MAX_BRICKS] = {};
    int brickColorIndex[MAX_BRICKS] = {};
    bool needsInit = true;

    // Multi-ball
    BallState balls[MAX_BALLS] = {};
    int activeBallCount = 1;

    // Capsules
    Capsule capsules[MAX_CAPSULES] = {};
    int capsuleW = 0, capsuleH = 0;
    float capsuleFallSpeed = 0;

    // Power-up state
    bool catchActive = false;
    int catchBallIndex = -1;
    float catchOffsetX = 0;
    int catchAutoReleaseTicks = 0;

    float originalBallSpeed = 0;
    int slowRecoveryTicks = 0;

    int originalPaddleW = 0;
    bool extendActive = false;

    bool laserActive = false;
    int laserCooldown = 0;
    int laserW = 0, laserH = 0;
    float laserSpeed = 0;

    bool exitOpen = false;

    float baseBallSpeed = 0;

    // Paddle
    float paddleX = 0;

    // Layout dimensions (calculated in onShow)
    int areaW = 0, areaH = 0;
    int cols = 0, rows = 0;
    int brickW = 0, brickH = 0;
    int brickGap = 0;
    int brickOffsetX = 0, brickOffsetY = 0;
    int ballSize = 0;
    int paddleW = 0, paddleH = 0;
    int paddleYPos = 0;
    float ballSpeed = 0;
    float paddleSpeed = 0;

    // Static callbacks
    static void onTick(lv_timer_t* timer);
    static void onPressed(lv_event_t* e);
    static void onClicked(lv_event_t* e);
    static void onKey(lv_event_t* e);
    static void onReenterKeyMode(lv_event_t* e);
    static void onPauseClicked(lv_event_t* e);
    static void onSoundToggled(lv_event_t* e);

    // Game logic
    void startGame();
    void nextLevel();
    void resetBall();
    void launchBall();
    void update();
    void checkLaserBrickCollisions();
    void loseLife();
    void winLevel();
    void createBricks();
    void setupLevelPattern();
    void refreshBricks();
    void updateScoreDisplay();
    void updateMessage();
    void togglePause();
    void updateSoundIcon();

    // Capsule system
    void spawnCapsule(float x, float y);
    void updateCapsules();
    void activatePowerUp(PowerUpType type);
    void clearPowerUps();
    void createCapsuleObjs();

    // Multi-ball
    void updateBalls();
    void splitBalls();

    // Laser
    void updateLasers();
    void fireLaser();
    void createLaserObjs();

    // BreakOut exit
    void openExit();
    void closeExit();

    // Brick helpers
    void hitBrick(int idx);
    int scoreBrick(int idx);

public:
    void onShow(AppHandle context, lv_obj_t* parent) override;
    void onHide(AppHandle context) override;
};
