#include <imgui/imgui.h>
#include <app.h>
#include <window.h>
#include <tinyxml2.h>
#include "levelEditor.h"
#include "editor.h"

using namespace tinyxml2;

namespace editor {

void LevelEditor::ShowNewTemplate()
{
    memset(templateName, 0, 256);
    templateTiming = songPosition;
    templateDuration = 1;
    showNewTemplate = true;
}

void LevelEditor::UpdateTemplates()
{
    if (showNewTemplate) {
        if (ImGui::Begin("New template", &showNewTemplate, {300, 200})) {

            ImGui::InputText("Name", templateName, 256);

            ImGui::InputFloat("Start", &templateTiming, 0.1, 1);
            ImGui::InputFloat("Length", &templateDuration, 0.1, 1);

            if (ImGui::Button("Create")) {
                CreateTemplate();
                showNewTemplate = false;
            }
        }

        ImGui::End();
    }

    if (showTemplateList) {
        if (ImGui::Begin("Template list", &showTemplateList, {300, 200})) {
            for (NotesTemplate *i: templates) {
                if (ImGui::Button(("Insert##" + i->name).c_str())) {
                    InsertTemplate(i);
                }
                ImGui::SameLine();
                ImGui::Text("%s (%d)", i->name.c_str(), i->notes.size());
                ImGui::SameLine();
                if (ImGui::Button(("Delete##" + i->name).c_str())) {
                    templates.remove(i);
                    delete i;

                    SaveTemplates();
                }
                ImGui::Separator();
            }
        }

        ImGui::End();
    }
}

void LevelEditor::CreateTemplate()
{
    NotesTemplate *temp = new NotesTemplate();

    temp->name = templateName;

    for (const game::noteInfo *i: notes) {
        if (i->time >= templateTiming && i->time <= templateTiming + templateDuration) {
            game::noteInfo *n = new game::noteInfo;
            memcpy(n, i, sizeof(game::noteInfo));
            n->time -= templateTiming;
            temp->notes.push_back(n);
        }
    }

    templates.push_back(temp);
    SaveTemplates();
}

void LevelEditor::LoadTemplates()
{
    for (NotesTemplate *i: templates) {
        delete i;
    }

    templates.clear();

    XMLDocument doc;

    std::string filename = "data/editor/" + info->name + ".xml";

    if (doc.LoadFile(filename.c_str()) != XML_SUCCESS) {
        return;
    }

    for (XMLElement *i = doc.RootElement()->FirstChildElement(); i; i = i->NextSiblingElement()) {
        NotesTemplate *temp = new NotesTemplate();
        temp->name = i->Attribute("name");

        for (XMLElement *j = i->FirstChildElement(); j; j = j->NextSiblingElement()) {
            game::noteInfo *note = new game::noteInfo;

            note->time = j->FloatAttribute("time");
            note->duration = j->FloatAttribute("duration");
            note->button = j->IntAttribute("button");
            note->type = j->IntAttribute("type");
            note->position.x = j->FloatAttribute("pos-x");
            note->position.y = j->FloatAttribute("pos-y");
            note->angle = j->FloatAttribute("angle");

            temp->notes.push_back(note);
        }

        templates.push_back(temp);
    }
}

void LevelEditor::SaveTemplates()
{
    XMLDocument doc;

    XMLElement *root = doc.NewElement("data");
    doc.InsertEndChild(root);

    for (const NotesTemplate *i: templates) {
        XMLElement *temp = doc.NewElement("template");

        temp->SetAttribute("name", i->name.c_str());

        for (const game::noteInfo *j: i->notes) {
            XMLElement *note = doc.NewElement("note");
            note->SetAttribute("time", j->time);
            note->SetAttribute("duration", j->duration);
            note->SetAttribute("button", j->button);
            note->SetAttribute("type", j->type);
            note->SetAttribute("pos-x", j->position.x);
            note->SetAttribute("pos-y", j->position.y);
            note->SetAttribute("angle", j->angle);

            temp->InsertEndChild(note);
        }

        root->InsertEndChild(temp);
    }

    std::string filename = "data/editor/" + info->name + ".xml";
    doc.SaveFile(filename.c_str());
}

void LevelEditor::InsertTemplate(const NotesTemplate *temp)
{
    float startTime = songPosition;
    float endTime = 0;

    for (const game::noteInfo *i: temp->notes) {
        float time = i->getEndTime();
        if (endTime < time) {
            endTime = time;
        }
    }

    endTime += songPosition;

    notes.remove_if([startTime, endTime](const game::noteInfo *note) {
        if (note->time <= endTime && note->getEndTime() >= startTime) {
            delete note; // память освободить не забыть бы
            return true;
        }

        return false;
    });

    for (const game::noteInfo *i: temp->notes) {
        game::noteInfo *note = new game::noteInfo;
        memcpy(note, i, sizeof(game::noteInfo));
        note->time += songPosition;
        notes.push_back(note);
    }

    SortNotes();
}

NotesTemplate::~NotesTemplate()
{
    for (auto i: notes) {
        delete i;
    }
}

}
