#include <eedb/widgets/DefaultNavigationBar.hpp>

#include <Wt/WMenu>
#include <Wt/WNavigationBar>
#include <Wt/WPopupMenu>
#include <Wt/WStackedWidget>

namespace std {

template <>
struct default_delete< Wt::WNavigationBar > {
    void operator()(Wt::WNavigationBar * ptr) {
        if(ptr && !ptr->parent())
            delete ptr;
    }
};
}

namespace eedb {

struct DefaultNavigationBar::DefaultNavigationBarPriv {
    void create() {
        if(_bar)
            // navigation bar is alredy created
            return;

        // Setup a Left-aligned menu.
        auto mainTabs = new Wt::WMenu();
        auto homeItem = mainTabs->addItem("Home");
        homeItem->setObjectName("navigation_bar.home_menu");
        homeItem->triggered().connect([=](auto...) {});

        // Setup a Right-aligned menu.
        // Create a popup submenu for the Help menu.
        auto sessionMenuPopup = new Wt::WPopupMenu();
        sessionMenuPopup->setObjectName("navigation_bar.session_menu_popup");

        auto logoutItem = sessionMenuPopup->addItem("Logout");
        logoutItem->setObjectName("navigation_bar.session_menu.logout");
        logoutItem->triggered().connect([=](auto...) { this->onLogin.emit(); });

        auto sessionItem = new Wt::WMenuItem("Session");
		sessionItem->setMenu(sessionMenuPopup);

        auto sessionMenu = new Wt::WMenu();
        sessionMenu->setObjectName("navigation_bar.session_menu");
        sessionMenu->addItem(sessionItem);

        _bar = std::make_unique< Wt::WNavigationBar >();
        _bar->setObjectName("navigation_bar");
        _bar->setTitle("eedb", "http://eedb.pl");
        _bar->setResponsive(true);
        _bar->addMenu(mainTabs, Wt::AlignLeft);
        _bar->addMenu(sessionMenu, Wt::AlignRight);
    }

    Wt::Signal<> onLogin;

    std::unique_ptr< Wt::WNavigationBar > _bar;
};

DefaultNavigationBar::DefaultNavigationBar() : _priv(std::make_unique< DefaultNavigationBarPriv >()) {}

DefaultNavigationBar::DefaultNavigationBar(DefaultNavigationBar && other) : _priv(std::move(other._priv)) {}

DefaultNavigationBar & DefaultNavigationBar::operator=(DefaultNavigationBar && other) {
    _priv = std::move(other._priv);
    return *this;
}

DefaultNavigationBar::~DefaultNavigationBar() = default;

void DefaultNavigationBar::attachTo(Wt::WContainerWidget * container) {
    _priv->create();
    container->addWidget(_priv->_bar.get());
}

void DefaultNavigationBar::detach() {
    auto parent = dynamic_cast< Wt::WContainerWidget * >(_priv->_bar->parent());
    if(parent)
        parent->removeWidget(_priv->_bar.get());
}

void DefaultNavigationBar::registerLogoutAction(std::function< void() > f) {
    _priv->onLogin.connect([f](auto...) { f(); });
}
}
