// service/BEService.h
#pragma once
#include "core/WinApi.h"
#include "services/GameMonitor.h"
#include <windows.h>

namespace BEService
{
    inline struct State
    {
        bool shouldStop = false;
        SERVICE_STATUS_HANDLE statusHandle = nullptr;

        void ReportRunning() const noexcept
        {
            SERVICE_STATUS STATUS
            {
                SERVICE_WIN32_OWN_PROCESS,
                SERVICE_RUNNING,
                SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN,
                NO_ERROR, 0, 0, 0
            };
            SetServiceStatus(statusHandle, &STATUS);
        }

        void ReportStopped() const noexcept
        {
            SERVICE_STATUS STATUS
            {
                SERVICE_WIN32_OWN_PROCESS,
                SERVICE_STOPPED,
                0, NO_ERROR, 0, 0, 0
            };
            SetServiceStatus(statusHandle, &STATUS);
        }
    } g_state;

    VOID WINAPI CtrlHandler(DWORD control) noexcept
    {
        if (control == SERVICE_CONTROL_STOP || control == SERVICE_CONTROL_SHUTDOWN)
            g_state.shouldStop = true;
    }

    VOID WINAPI ServiceMain(DWORD, LPWSTR*) noexcept
    {
        g_state.statusHandle = RegisterServiceCtrlHandlerW(L"BEService", CtrlHandler);
        if (!g_state.statusHandle)
            return;

        g_state.ReportRunning();

        if (!GameMonitor::WaitForGame() || g_state.shouldStop)
            goto cleanup;

        while (!g_state.shouldStop && GameMonitor::IsGameRunning())
            Sleep(1000);

        if (!g_state.shouldStop)
            Sleep(5000);

    cleanup:
        g_state.ReportStopped();
    }

    [[nodiscard]] inline bool Run() noexcept
    {
        SERVICE_TABLE_ENTRYW table[] = {
            { const_cast<wchar_t*>(L"BEService"), ServiceMain },
            { nullptr, nullptr }
        };

        return StartServiceCtrlDispatcherW(table) != FALSE;
    }
}