#include "Client.hpp"
#include "../server/config.hpp"
#include <imgui.h>
#include <imgui_stdlib.h>
#include "render/UI.hpp"

struct ServerFactory: public world::AbstractServerFactory {
    ServerFactory(config::server::options& options):
        options(options) { }
    ~ServerFactory() {
        if (serverTask.joinable())
            serverTask.join();

        if (server != nullptr)
            delete server;
    }

    config::server::options& options;
    std::thread serverTask;
    Server* server = nullptr;

    world::server_handle* run() override {
        if (server != nullptr) {
            LOG_E("Previous server still running");
            return server->getHandle();
        }
        if (serverTask.joinable())
            serverTask.join();

        LOG_W("Starting local server");
        server = new Server(options);
        serverTask = std::thread([&] {
#if TRACY_ENABLE
            tracy::SetThreadName("Server");
#endif
            server->run();
            delete server;
            server = nullptr;
        });
        return server->getHandle();
    }

    void onGui() override {
        const auto running = server && server->getHandle()->running;
        {
            ImGui::Columns(2, NULL, false);
            ImGui::Text("Status: %s", server ? (running ? "running" : "stopping") : "stopped");
            ImGui::NextColumn();
            const auto btnSize = ImVec2(ImGui::GetWindowContentRegionWidth()/2, 0);
            if (running) {
                if (ImGui::Button("Stop", btnSize))
                    server->getHandle()->running = false;
            } else if (!server) {
                if (ImGui::Button("Start", btnSize))
                    run();
            }
            ImGui::Columns();
        }
        ImGui::Separator();
        {
            int load = options.world.loadDistance;
            int keep = options.world.keepDistance;
            if (ImGui::SliderInt("Load distance", &load, 1, options.world.keepDistance) |
                ImGui::SliderInt("Keep distance", &keep, options.world.loadDistance + 1, 21)) {
                options.world.loadDistance = load;
                options.world.keepDistance = keep;
            }
            ImGui::InputText("Path", &options.world.folderPath);
            int flood = options.world.floodFillLimit;
            if (ImGui::InputInt("Max part size", &flood, 1, 128)) {
                options.world.floodFillLimit = flood;
            }
        }
        if (ImGui::CollapsingHeader("Connection", ImGuiTreeNodeFlags_DefaultOpen)) {
            if (running) {
                ImGui::PushStyleVarDisabled();
            }
            const auto textFlags = running ? ImGuiInputTextFlags_ReadOnly : 0;
            ImGui::InputText("Host", &options.connection.host, textFlags);
            ImGui::InputInt("Port", &options.connection.port, textFlags);
            ImGui::InputText("Key", &options.connection.key, textFlags);
            ImGui::InputText("Cert", &options.connection.cert, textFlags);
            int max_con = options.connection.max_connections;
            if (ImGui::InputInt("Max connections", &max_con) && !running) {
                options.connection.max_connections = max_con;
            }
            ImGui::Checkbox("Allow local", &options.allowLocal);
            if (running) {
                ImGui::PopStyleVar();
            }
        }
        if (ImGui::CollapsingHeader("Clock", ImGuiTreeNodeFlags_DefaultOpen)) {
            int tps = options.tps;
            if (ImGui::SliderInt("Tick per second", &tps, 1, 60)) {
                options.tps = tps;
            }
            int upt = options.upt;
            if (ImGui::SliderInt("Update per tick", &upt, 1, 10)) {
                options.upt = upt;
            }
            int rng = options.world.randomTick;
            if (ImGui::SliderInt("Random tick", &rng, 1, 1024)) {
                options.world.randomTick = rng;
            }
        }
    }
};