#include <Wt/WBootstrap5Theme.h>
#include <Wt/WDialog.h>
#include <Wt/WEnvironment.h>
#include <Wt/WHBoxLayout.h>
#include <Wt/WPushButton.h>
#include <Wt/WServer.h>
#include <Wt/WVBoxLayout.h>
#include <Wt/WWidgetItem.h>

class GridApplication : public Wt::WApplication
{
public:
    GridApplication(const Wt::WEnvironment &env) : Wt::WApplication(env)
    {
        auto appTheme = std::make_shared<Wt::WBootstrap5Theme>();

        setTheme(appTheme);

        auto layout = root()->setLayout(std::make_unique<Wt::WVBoxLayout>());

        auto hLayout = layout->addLayout(std::make_unique<Wt::WHBoxLayout>());

        auto button  = hLayout->addWidget(std::make_unique<Wt::WPushButton>("Replace Host Container"));
        auto button2 = hLayout->addWidget(std::make_unique<Wt::WPushButton>("Replace Content Container"));

        auto container = buildContainer();
        replaceHostContainer(layout, std::move(container));

        button->clicked().connect([this, layout]() {
            auto container = buildContainer();
            std::cout << "Replace Host Container" << std::endl;
            replaceHostContainer(layout, std::move(container));
        });

        button2->clicked().connect([this, layout]() {
            auto container = buildContainer();
            std::cout << "Replace Content Container" << std::endl;
            // replaceContentContainer(layout, std::move(container));
            replaceContentContainerVariante2();
            // layout->setStretchFactor(m_hostContainer, 1);
        });
    }

private:
    void replaceHostContainer(Wt::WVBoxLayout *layout, std::unique_ptr<Wt::WContainerWidget> container)
    {
        if (m_hostContainer != nullptr)
        {
            m_hostContainer->removeFromParent();
            m_hostContainer = nullptr;
        }

        m_hostContainer = layout->addWidget(std::make_unique<Wt::WContainerWidget>(), 1);

        auto hostLayout = m_hostContainer->setLayout(std::make_unique<Wt::WVBoxLayout>());

        m_contentContainer = hostLayout->addWidget(std::move(container), 1);
    }

    void replaceContentContainer(Wt::WVBoxLayout *layout, std::unique_ptr<Wt::WContainerWidget> container)
    {
        if (m_hostContainer == nullptr)
        {
            m_hostContainer = layout->addWidget(std::move(container), 1);
        }

        if (m_contentContainer != nullptr)
        {
            m_contentContainer->removeFromParent();
            m_contentContainer = nullptr;
        }

        m_contentContainer = m_hostContainer->addWidget(std::move(container));
    }

    void replaceContentContainerVariante2()
    {
        auto layout = m_contentContainer->layout();

        while (layout->count() > 0)
        {
            auto widget = layout->itemAt(0)->widget();
            layout->removeWidget(widget);
        }
        buildVBoxLayout(m_contentContainer, false);
    }

    void buildVBoxLayout(Wt::WContainerWidget *container, bool setLayout = true)
    {
        Wt::WVBoxLayout *vboxLayout = nullptr;

        if (setLayout)
            vboxLayout = container->setLayout(std::make_unique<Wt::WVBoxLayout>());
        else
            vboxLayout = dynamic_cast<Wt::WVBoxLayout *>(container->layout());

        for (int i = 0; i < 4; i++)
        {
            int number = std::rand() % 10;

            vboxLayout->addWidget(std::make_unique<Wt::WText>("Text" + std::to_string(number)));
        }
    }

    void buildGridLayout(Wt::WContainerWidget *container)
    {
        auto gridLayout = container->setLayout(std::make_unique<Wt::WGridLayout>());

        for (int i = 0; i < 4; i++)
        {
            int number = std::rand() % 10;

            gridLayout->addWidget(
                std::make_unique<Wt::WText>("Text" + std::to_string(number)),
                i,
                0,
                Wt::AlignmentFlag::Justify | Wt::AlignmentFlag::Top);

            gridLayout->addWidget(
                std::make_unique<Wt::WText>("Value" + std::to_string(number)),
                i,
                1,
                Wt::AlignmentFlag::Justify | Wt::AlignmentFlag::Top);
        }
    }

    std::unique_ptr<Wt::WContainerWidget> buildContainer()
    {
        auto container = std::make_unique<Wt::WContainerWidget>();
        buildVBoxLayout(container.get());

        return container;
    }

    Wt::WContainerWidget *m_hostContainer    = nullptr;
    Wt::WContainerWidget *m_contentContainer = nullptr;
};

std::unique_ptr<Wt::WApplication> createApplication(const Wt::WEnvironment &env)
{
    auto app = std::make_unique<GridApplication>(env);

    return app;
}

int main(int argc, char **argv)
{
    try
    {
        Wt::WServer server(argc, argv, WTHTTP_CONFIGURATION);

        server.addEntryPoint(Wt::EntryPointType::Application, std::bind(createApplication, std::placeholders::_1));
        // Wt::WLayout::setDefaultImplementation(Wt::LayoutImplementation::JavaScript);

        server.run();
    }
    catch (Wt::WException &e)
    {
        std::cerr << "Exception: " << e.what() << std::endl;
    }
}
