#pragma once
#include <atomic>
#include <memory>
#include <string>
#include <thread>
#include "api_server.hpp"
#include "database.hpp"
#include "dispatcher.hpp"
#include "key_store.hpp"
#include "poller.hpp"
#include "runtime_state.hpp"
#include "subscription_store.hpp"
#include "telegram_client.hpp"
namespace telegrammer
{
/// Contains the validated settings and held lock for one daemon instance.
struct ApplicationConfig
{
/// Address and port for the authenticated HTTP API.
mw::IPSocketInfo listen_info;
/// Telegram bot token used by the production client.
std::string token;
/// SQLite state database path.
std::string db_path;
/// Exclusive daemon lock retained for the application lifetime.
std::unique_ptr<DatabaseLock> database_lock;
};
/// Owns the daemon components and coordinates their complete lifecycle.
class Application
{
public:
/// Construct a daemon from validated configuration and a held lock.
explicit Application(ApplicationConfig config);
/// Start, run, and cleanly stop the daemon.
int run();
private:
std::unique_ptr<DatabaseLock> database_lock_;
mw::IPSocketInfo listen_info_;
std::string db_path_;
KeyStore keys_;
SubscriptionStore subscriptions_;
DeliveryStore deliveries_;
TelegramClient telegram_;
RuntimeState state_;
Dispatcher dispatcher_;
Poller poller_;
ApiServer server_;
std::jthread signal_watcher_;
std::atomic<bool> stopping_ = false;
void requestStop();
void waitForSignal(std::stop_token stop_token);
};
} // namespace telegrammer