#pragma once

#include <chrono>

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>

using TimePoint = std::chrono::steady_clock::time_point;
using TimeDuration = std::chrono::duration<double>;

struct Player
{
    sf::RectangleShape body{};

    sf::Vector2f pos{};
    sf::Vector2f prevPos{};
    float velocity{5};
    unsigned int score{};
    bool up{false};
    bool down{false};
};

struct Cpu
{
    sf::RectangleShape body{};

    sf::Vector2f pos{};
    sf::Vector2f prevPos{};
    float velocity{};
    float speed{5};
    unsigned int score{};
};

struct Ball
{
    sf::CircleShape body{};

    sf::Vector2f pos{};
    sf::Vector2f prevPos{};
    sf::Vector2f velocity{};
    float speed{};
    sf::Angle angle{};
};

class Game
{
public:
    void init();

    void run();

    void getInput();

    void render();

    void updateCpu();

    void updatePlayer();

    void updateBall();

    void collision();

    void updateTexts();

    void soundSystem();

    void resetGame();

private:
    sf::RenderWindow window {sf::VideoMode({1280u, 720u}), "project-pong"};
    std::chrono::steady_clock clock;

    sf::RectangleShape midline{};
    sf::RectangleShape gameBoundary{};

    sf::Font font{};

    sf::Text playerScore{font};
    sf::Text cpuScore{font};
    sf::Text time{font};

    sf::SoundBuffer bgMusicBuffer;
    sf::SoundBuffer failSoundBuffer;
    sf::SoundBuffer winSoundBuffer;
    sf::SoundBuffer hitSoundBuffer;
    sf::SoundBuffer scoreSoundBuffer;

    sf::Sound bgMusic{bgMusicBuffer};
    sf::Sound failSound{failSoundBuffer};
    sf::Sound winSound{winSoundBuffer};
    sf::Sound hitSound{hitSoundBuffer};
    sf::Sound scoreSound{scoreSoundBuffer};

    size_t frameCount{};

    Player player{};
    Ball ball{};
    Cpu cpu{};

    const double physicsDeltaTime = 1.0 / 60.0;
    const double targetFps = 60.0;
    const double targetFrameTime = 1.0 / targetFps;

    double accumulator{};

    TimeDuration playTime{};
    std::chrono::seconds totalSeconds{};

};