#pragma once

#include <render/camera.h>
#include <render/sprite/atlas.h>
#include <render/sprite/image.h>
#include <render/text/text.h>
#include <soloud_wavstream.h>
#include "scene.h"
#include "defs.hpp"
#include "noteManager.hpp"
#include "buttonManager.h"
#include "healthBar.h"

namespace game {

enum class NoteResult
{
    wrong = 0,
    miss,
    almost,
    ok,
    great
};

enum class StartFlags
{
    immortality = 1<<0,
    noHeals = 1<<1,
    relaxedTimings = 1<<2,
    hardenedTimings = 1<<3,
    noDoubleNotes = 1<<4,
};

struct currentLevelStatistic
{
    uint32_t wrongButtons;
    uint32_t almostButtons;
    uint32_t okButtons;
    uint32_t greatButtons;

    uint32_t maxCombo;
    uint32_t score;
};

class Level: public Scene
{
    render::camera *camera;
    render::sprite::image *background;
    render::text::Font *font;
    render::text::text *comboText, *scoreText;

    SoLoud::WavStream *music;
    SoLoud::handle playingHandler;

    NoteManager *manager;
    ButtonManager *controlManager;

    std::list<game::noteInfo*> notes;

    float songPosition;
    float songLength;
    float fadeTime;

    bool shouldClose;

    int score;
    int health;
    int combo;

    HealthBar healthBar;

    bool paused, showSettings;
    vec2f comboPosition;
    float comboShowTime;

    uint32_t flags;

public:

    uint32_t startFlags;

    currentLevelStatistic statistic;

    const levelInfo *info;

    Level();
    virtual ~Level();

    float GetSoundLength() const;
    bool IsFailed() const;
    int GetNoteCount() const;
    uint32_t GetFlags() const;

    void Load(levelInfo *info);
    void Show();
    void Hide();

    void Start();
    void Pause();
    void Reset();

    void Update();
    void Render();

    void AddNoteResult(NoteResult result, const noteInfo *note);
private:

    void LoadNotes();
    void UpdateMenu();

    void UpdateGui();
    void RenderGui();

    void PrepareComboText(NoteResult);
    void MakeFade();

    void SetSoundVolume(float volume);
};

}
