#pragma once
#include <list>

#include "ball.hpp"
#include "brick_grid.hpp"
#include "paddle.hpp"
class Bonus;
class Effect;

class Arkanoid
{
private:
    // Константы:
    // Цвет задника
    const sf::Color kBackgroundColor {12, 31, 47};
    // Максимально возможное количество шариков в один момент времени
    const unsigned kMaxNumBalls {250};
    // Максимально возможное количество бонусов в один момент времени
    const unsigned kMaxNumBonuses {10};

    // Время, которое прошло с начала игры в секундах
    double m_time;
    // Границы игрового поля
    sf::FloatRect m_border;
    // Связный список всех шариков
    std::list<Ball> m_balls;
    // Объект, задающий состояние сетки блоков
    BrickGrid m_brickGrid;
    // Ракетка
    Paddle m_paddle;
    // Состояние игры
    enum class GameState {stuck, running, endLose, endWin};
    GameState m_gameState;

    // Текущее число жизней
    int m_numLives;

    // Связный список указателей на бонусы
    // Почему указатели - для реализации полиформизма
    // Так как в будущем мы хотим сделать несколько вариантов бонусов
    std::list<Bonus*> m_bonuses;
    std::list<Effect*> m_effects;

    // Вероятность того, что при разрушении блока выпадет бонус
    float m_bonusProbability;

    // Макет шарика, используемый для рисова
    Ball m_initialBall {6, {0, 0}, {0, 0}};

    // Текст, который рисуется в конце игры
    sf::Text m_endText;


    void addRandomBonus(sf::Vector2f position);

    // Функция, которая обрабатывает все столкновения шарика 
    void handleBallCollisions(Ball& ball);

public:
    Arkanoid(sf::FloatRect border, sf::Font& font);

    sf::FloatRect getBorder() const;

    const Paddle& getPaddle() const;

    const BrickGrid& getBrickGrid() const;

    void addBall(const Ball& ball);

    // Эта функция вызывается каждый кадр
    void update(const sf::RenderWindow& window, float dt);

    void draw(sf::RenderWindow& window);
    void onMousePressed(sf::Event& event);
    bool isMaxBalls();
    
    // Класс бонус должен быть дружественным, так как он может менять внутреннее состояние игры
    friend class Bonus;
    friend class TripleBallBonus;
    friend class EnlargePaddleBonus;
    friend class ShrinkPaddleBonus;
    friend class SlowingBonus;

    friend class SlowingEffect;
};
