#include "application/application.h"
#include "core/gameevent.h"
#include "core/editor.h"

#include "application/mainmenu.h"
#include "application/gamestate.h"
#include "application/editorstate.h"
#include "application/about.h"

#include "classicmode/classicfactory.h"

bool Application::init()
{
    if (!_core_factory)
        return false;

    MainMenu::Callbacks callbacks =
    {
        [&](){ pushState(GUIState::Tag::GAME); },
        [&](){ pushState(GUIState::Tag::EDITOR); },
        [&](){ pushState(GUIState::Tag::ABOUT); },
    };

    const auto main_menu = std::make_shared<MainMenu>(_core_factory, std::move(callbacks));
    const auto game_state = std::make_shared<GameState>(_core_factory, classic::getGame(_core_factory), GameState::Callbacks{[&](){ popState(); }});
    const auto editor = std::make_shared<EditorState>(_core_factory, classic::getEditor(_core_factory), EditorState::Callbacks{[&](){ popState(); }});
    const auto about = std::make_shared<About>(_core_factory, About::Callbacks{[&](){ popState(); }});

    _states[GUIState::Tag::MAIN_MENU] = main_menu;
    _states[GUIState::Tag::GAME] = game_state;
    _states[GUIState::Tag::EDITOR] = editor;
    _states[GUIState::Tag::ABOUT] = about;

    pushState(GUIState::Tag::MAIN_MENU);

    return true;
}

void Application::input(const kku::SystemEvent& event)
{
    _state_stack.back()->input(event);
}

void Application::update(const kku::microsec& dt)
{
    _state_stack.back()->update(dt);
}

void Application::pushState(GUIState::Tag new_state)
{
    if (!_state_stack.empty())
        _state_stack.back()->leave();

    _state_stack.emplace_back(_states.at(new_state));
    _state_stack.back()->enter();
}

void Application::popState()
{
    _state_stack.back()->leave();
    _state_stack.pop_back();
    _state_stack.back()->enter();
}
