#pragma once

#include "admin_manager.h"
#include "connection.h"
#include "thread_info.h"

#include <balancer/kernel/coro/own_executor.h>
#include <balancer/kernel/ctl/ctl.h>
#include <balancer/kernel/module/events.h>
#include <balancer/kernel/process/thread_info.h>

#include <library/cpp/coroutine/listener/listen.h>
#include <util/generic/adaptor.h>
#include <util/thread/singleton.h>

using namespace NConfig;

namespace NSrvKernel::NProcessCore {
    class TMainEventHandler: public TEventHandler {
    public:
        TMainEventHandler() {
            Register("dump_shared_files", "instance.DumpSharedFiles", &TMainEventHandler::DumpSharedFiles, this);
        };

        void DumpSharedFiles(TEventData& event) {
            Y_ASSERT(FastTlsSingleton<TThreadInfo>()->WorkerProcess);
            FastTlsSingleton<TThreadInfo>()->WorkerProcess->DumpSharedFiles(event.Out());
        }
    };


    class TMainStats {
    public:
        TMainStats(TSharedStatsManager& statsManager)
            : CancelledConns(statsManager.MakeCounter("worker-cancelled_conns").Build())
            , TcpConns(statsManager.MakeGauge("worker-tcp_conns").Build())
            , TcpConnsOpen(statsManager.MakeCounter("worker-tcp_conns_open").Build())
            , TcpConnsClose(statsManager.MakeCounter("worker-tcp_conns_close").Build())
            , TcpMaxConns(statsManager.MakeGauge("worker-tcp_max_conns").Build())
            , AllocatedSharedMemory(statsManager.MakeGauge("allocated_shared_memory").Build())
            , MappedSharedMemory(statsManager.MakeGauge("mapped_shared_memory").Build())
            , ProcessedLogItems(statsManager.MakeCounter("worker-processed_log_items").Build())
            , LostLogItems(statsManager.MakeCounter("worker-lost_log_items").Build())
            , FDSize(statsManager.MakeGauge("fd_size").Build())
            , NoFileLimit(statsManager.MakeGauge("no_file_limit").Build())
            , ConnectionsCounter_(statsManager.MakeCounter("worker-connections_count").Build())
        {}

        TMainStats(const TMainStats& mainStats, size_t workerId)
            : CancelledConns(mainStats.CancelledConns, workerId)
            , TcpConns(mainStats.TcpConns, workerId)
            , TcpConnsOpen(mainStats.TcpConnsOpen, workerId)
            , TcpConnsClose(mainStats.TcpConnsClose, workerId)
            , TcpMaxConns(mainStats.TcpMaxConns, workerId)
            , AllocatedSharedMemory(mainStats.AllocatedSharedMemory, workerId)
            , MappedSharedMemory(mainStats.MappedSharedMemory, workerId)
            , ProcessedLogItems(mainStats.ProcessedLogItems, workerId)
            , LostLogItems(mainStats.LostLogItems, workerId)
            , FDSize(mainStats.FDSize, 0)
            , NoFileLimit(mainStats.NoFileLimit, 0)
            , ConnectionsCounter_(mainStats.ConnectionsCounter_, workerId)
        {}

        TSharedCounter& ConnectionsCounter() noexcept {
            return ConnectionsCounter_;
        }

    public:
        TSharedCounter CancelledConns;
        TSharedCounter TcpConns;
        TSharedCounter TcpConnsOpen;
        TSharedCounter TcpConnsClose;
        TSharedCounter TcpMaxConns;
        TSharedCounter AllocatedSharedMemory;
        TSharedCounter MappedSharedMemory;
        TSharedCounter ProcessedLogItems;
        TSharedCounter LostLogItems;
        TSharedCounter FDSize;
        TSharedCounter NoFileLimit;

    private:
        TSharedCounter ConnectionsCounter_;
    };

    struct TMainConfig;

    class TStatsCallback : public TContListener::ICallBack {
    public:
        TStatsCallback(TSharedCounter& connectionsCounter, const TMainConfig& mainConfig,
            TContExecutor& executor, TSharedStatsManager& statsManager, TMasterProcess& masterProcess, TSystemLog& log);

        void OnAcceptFull(const TAcceptFull& acc) override;
        void OnError() override;
        void OnStop(TSocketHolder* s) override;

    public:
        TSharedCounter& ConnectionsCounter;
        size_t InProgr = 0;
        const size_t BufferSize = 0;
        TContExecutor& Executor;
        TSystemLog& Log;
        TMasterProcess& MasterProcess;

    private:
        const size_t MaxStatsConnections_ = 0;
        TSharedStatsManager& StatsManager_;
        TIntrusiveList<TStatsConnection> StatsConnections_;
    };

    class TAdminCallback : public TContListener::ICallBack {
    public:
        TAdminCallback(TSharedCounter& connectionsCounter, const TMainConfig& mainConfig,
            TContExecutor& executor, TMasterProcess& masterProcess, TMainTask& mainTask, TSystemLog& log);

        void OnAcceptFull(const TAcceptFull& acc) override;
        void OnError() override;
        void OnStop(TSocketHolder* s) override;

    public:
        TSharedCounter& ConnectionsCounter;
        size_t InProgr = 0;
        const size_t BufferSize = 0;
        TContExecutor& Executor;
        TSystemLog& Log;
        TMasterProcess& MasterProcess;
        TMainTask& MainTask;

    private:
        const size_t MaxAdminConnections_ = 0;
        TAdminManager AdminManager_;
        TIntrusiveList<TAdminConnection> AdminConnections_;
    };
}
