#include <imgui/imgui.h>
#include <tinyxml2.h>
#include <app.h>
#include <window.h>
#include "game.h"
#include "menu.h"
#include "level.h"
#include "settingsMenu.h"

namespace game {

Menu::Menu()
{
    state = MenuState::mainMenu;
    stats = new Statistic();
}

Menu::~Menu()
{
    delete stats;
}

void Menu::Show()
{

}

void Menu::Update()
{
    switch (state) {
    case MenuState::levelSelector:
        UpdateLevelSelector();
        if (App::GetInput()->IsControlJustPressed(INPUT_BACK)) {
            state = MenuState::mainMenu;
        }
        break;
    case MenuState::mainMenu:
        UpdateMainMenu();
        break;
    case MenuState::settings:
        UpdateSettings();
        break;
    case MenuState::levelResult:
        UpdateLevelResult();
        break;
    case MenuState::levelPreview:
        UpdateLevelSelector();
        UpdateLevelPreview();

        if (App::GetInput()->IsControlJustPressed(INPUT_BACK)) {
            state = MenuState::levelSelector;
        }

        break;
    }

    if (oldState != state) {
        oldState = state;
        render::setClearColor(color::hsv2rgba(vec3f(rand()%360, 1, 0.05)));
    }
}

void Menu::UpdateSettings()
{
    if (SettingsMenu::Update()) {
        state = MenuState::mainMenu;
    }
}

void Menu::UpdateMainMenu()
{
    ImGui::SetNextWindowPos({0, 200}, ImGuiCond_Always);
    ImGui::Begin("IGDC#165", nullptr, {960, 230}, 1, ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDecoration);

    if (ImGui::Button("Free play", {300, 50})) {
        LoadLevelList();
        state = MenuState::levelSelector;
    }
    if (ImGui::Button("Editor", {300, 50})) {
        LoadLevelList();
        game::SetState(gameState::stateEditor);
    }
    if (ImGui::Button("Settings", {300, 50})) {
        state = MenuState::settings;
    }
    if (ImGui::Button("Quit", {300, 50})) {
        window::setShouldClose(true);
    }

    ImGui::End();
}

void Menu::UpdateLevelSelector()
{
    ImGui::SetNextWindowPos({0, 0}, ImGuiCond_Always);
    ImGui::Begin("LEVEL_SELECTOR", nullptr, {320, 544}, 1, ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDecoration);

    for (auto &i: levelList) {
        if (ImGui::Button(i->name.c_str(), {300, 50})) {
            game::GetLevel()->Load(i);
            state = MenuState::levelPreview;
            break;
        }
    }

    ImGui::Separator();

    if (ImGui::Button("Back", {300, 50})) {
        state = MenuState::mainMenu;
    }

    ImGui::End();
}

void Menu::UpdateLevelPreview()
{
    Level *level = game::GetLevel();
    const levelStatistic *record = stats->GetLevelStatistic(level->info->name);

    ImGui::SetNextWindowPos({320, 0}, ImGuiCond_Always);
    ImGui::Begin("LEVEL_PREVIEW", nullptr, {640, 544}, 1, ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDecoration);

    ImGui::Text(level->info->name.c_str());

    ImGui::Separator();

    float songLength = level->GetSoundLength();
    ImGui::Text("Song length %02d:%02d", (int) songLength/60, (int) songLength % 60);
    ImGui::Text("Note count: %d", level->GetNoteCount());
    ImGui::Separator();

    if (record) {
        ImGui::Text("High score: %d", record->score);
        ImGui::Text("Max combo: %d", record->maxCombo);
        ImGui::Text("Grade: %d", record->grade);
        ImGui::Text("Times played: %d", record->played);
        ImGui::Separator();
    }

    ImGui::Text("Helpers:");

    if (ImGui::CheckboxFlags("Immortality", &level->startFlags, (uint32_t) StartFlags::immortality)) {
        level->startFlags &= ~(uint32_t) StartFlags::noHeals;
    }

    ImGui::SameLine();

    if (ImGui::CheckboxFlags("Relaxed timings", &level->startFlags, (uint32_t) StartFlags::relaxedTimings)) {
        level->startFlags &= ~(uint32_t) StartFlags::hardenedTimings;
    }

    ImGui::Separator();

    ImGui::Text("Chalengers:");

    if (ImGui::CheckboxFlags("Ho heals", &level->startFlags, (uint32_t) StartFlags::noHeals)) {
        level->startFlags &= ~(uint32_t) StartFlags::immortality;
    }
    ImGui::SameLine();
    if (ImGui::CheckboxFlags("Hardened timings", &level->startFlags, (uint32_t) StartFlags::hardenedTimings)) {
        level->startFlags &= ~(uint32_t) StartFlags::relaxedTimings;
    }
    ImGui::Separator();

    if (ImGui::Button("Play", {300, 50})) {
        state = MenuState::levelResult;
        shouldSaveStatistic = true;
        game::SetState(gameState::stateInGame);
    }

    ImGui::End();
}

void Menu::UpdateLevelResult()
{
    const Level *level = game::GetLevel();
    levelStatistic record;
    stats->GetLevelStatistic(level->info->name, &record);

    ImGui::SetNextWindowPos({0, 0}, ImGuiCond_Always);
    ImGui::Begin("LEVEL_RESULT", nullptr, {960, 544}, 1, ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDecoration);

    ImGui::Text(level->info->name.c_str());

    float grade = (float) level->statistic.greatButtons / (float) level->GetNoteCount();
    grade += (float) level->statistic.okButtons / (float) level->GetNoteCount() / 2;
    grade *= 100;

    if (level->IsFailed()) {
        ImGui::TextColored(ImColor(0xff0034ff), "FAILED");
    } else {
        ImGui::Text("GRADE %02.1f%%", grade);
    }

    ImGui::Dummy({0, 20});

    ImGui::Separator();
    ImGui::Text("Total notes: %d", level->GetNoteCount());

    if (level->statistic.maxCombo == level->GetNoteCount()) {
        ImGui::TextColored(ImColor(0xfeae34ff), "Max combo: %d  FULL COMBO!", level->statistic.maxCombo);
    } else {
        ImGui::Text("Max combo: %d", level->statistic.maxCombo);
    }
    ImGui::Separator();

    ImGui::Dummy({0, 20});

    ImGui::Separator();
    ImGui::Text("Great: %d", level->statistic.greatButtons);
    ImGui::Text("Good: %d", level->statistic.okButtons);
    ImGui::Text("Almost: %d", level->statistic.almostButtons);
    ImGui::Text("Miss: %d", level->statistic.wrongButtons);
    ImGui::Separator();

    ImGui::Dummy({0, 20});

    ImGui::Separator();
    ImGui::Text("Score: %d", level->statistic.score);


    if (level->statistic.score > record.score) {
        ImGui::TextColored(ImColor(0xfeae34ff), "High score: %d NEW HIGH SCORE!", level->statistic.score);
    } else {
        ImGui::Text("High score: %d", record.score);
    }

    ImGui::Separator();

    if (ImGui::Button("Again", {300, 50})) {
        state = MenuState::levelPreview;
    }

    ImGui::SameLine();

    if (ImGui::Button("Back", {300, 50})) {
        state = MenuState::levelSelector;
    }

    ImGui::End();

    if (shouldSaveStatistic) {

        record.grade = grade;
        record.maxCombo = level->statistic.maxCombo;
        record.played++;
        record.score = level->statistic.score;

        stats->SetLevelStatistic(level->info->name, &record);
        stats->Save();

        shouldSaveStatistic = false;
    }
}

void Menu::LoadLevelList()
{
    for (auto i: levelList) {
        delete i;
    }

    levelList.clear();

    tinyxml2::XMLDocument doc;
    doc.LoadFile("data/level.xml");

    tinyxml2::XMLElement *el = doc.RootElement()->FirstChildElement();

    do {
        game::levelInfo *temp = new game::levelInfo;

        temp->name = el->Attribute("name");
        temp->notesFile = el->Attribute("notes");
        temp->musicFile = el->Attribute("bgm");
        temp->backgroundFile = el->Attribute("bgi");
        temp->speed = el->FloatAttribute("speed");

        levelList.push_back(temp);

    } while ((el = el->NextSiblingElement()));
}


}

