#ifndef DEBUGGERS_H
#define DEBUGGERS_H

#include "olcPGEX_Sound.h"
#include "olcPixelGameEngine.h"

#include "bonus.h"
#include "button.h"
#include "bug.h"
#include "player.h"
#include "programmer.h"
#include "game_state.h"

#include <chrono>
#include <list>
#include <map>
#include <random>
#include <string>
#include <vector>

namespace pabloader {

class Debuggers : public olc::PixelGameEngine {
private:
    std::list<Programmer*> programmers;
    std::list<Bonus*> bonuses;
    std::list<Button*> buttons;

    std::map<BonusType, uint32_t> bonusesCatched;

    uint32_t bugsCatched = 0;
    uint32_t bugsCatchedByPlayer = 0;
    uint32_t bugsMissed = 0;

    uint8_t linesOfCode = 5;
    uint16_t totalLines;
    std::list<std::string> originalSourceCode;
    std::list<std::string> sourceCode;

    GameState state = STATE_MAIN_MENU;
    GameState prevState;
    float helpRotation = 0;

    std::mt19937 generator;

public:
    Debuggers()
        : generator(std::chrono::system_clock::now().time_since_epoch().count())
    {
        sAppName = "Debuggers";
    }

public:
    bool OnUserCreate() override;
    bool OnUserUpdate(float fElapsedTime) override;
    bool OnUserDestroy() override;
    int GameScreenHeight() { return ScreenHeight() - linesOfCode * 10; }
    GameState GetState() { return state; }
    void SwitchState(GameState newState);

    template <typename T>
    T GetRandom(T from = 0, T to = 1);

private:
    void ResetGame();
    void ClearButtons();
    void DrawMenu();
    void DrawSourceCode();
    void DrawLogo();

    void SpawnPlayer();
    void SpawnProgrammer();
    void SpawnBug();
    void SpawnBonus();
    Bug* CreateBug();
    Bonus* CreateBonus();

private: // Gamemodes
    bool MainMenu(float dt);
    bool GamePlay(float dt);
    bool PauseMenu(float dt);
    bool GameOver(float dt);
    bool HelpMenu(float dt);

public:
    std::list<Bug*> bugs;

    olc::ResourcePack pack;

    olc::Sprite playerSprite;
    olc::Sprite enemiesSprite;
    olc::Sprite bonusesSprite;
    olc::Sprite backgroundSprite;

    int bgMusic;

    int playerFallSample;
    int bugFallSample;
    int bugCatchSample;
    int hoverSample;
    int clickSample;

    const int gravity = 25;
#ifdef _DEBUG
    bool debug = false;
#endif
};
}

#endif