#pragma once

#include <library/cpp/http/static/static.h>

#include <library/cpp/deprecated/atomic/atomic.h>
#include <util/system/mutex.h>

class THttpServer;

struct TSearchServerBase: THttpServer::ICallBack, CHttpServerStatic {
public:
    TSearchServerBase(const THttpServerOptions& options, size_t servers = 1);
    ~TSearchServerBase();

    bool ClientConnected();
    void Start();     // sync call
    void Stop();      // sync call

    void ShutdownAndWait(); // sync call

    bool IsRunning();

protected:
    virtual void OnFailRequestEx(const TFailLogData& d) override;
    virtual void OnListenStart() override;
    virtual void OnListenStop() override;

private:
    bool IsRunningUnsafe(const TGuard<TMutex>&); // fake parameter to ensure it's called under the lock

private:
    TMutex StateLock;
    TAtomic RunningCounter;
    TVector<THolder<THttpServer>> HttpServers;
};

template <class TConfigType>
class TSearchServerAbstract: public TSearchServerBase {
public:
    typedef TConfigType TConfig;

protected:
    const TConfig& Config;

public:
    inline TSearchServerAbstract(const TConfig& config)
        : TSearchServerBase(config.GetHttpServerOptions())
        , Config(config)
    {
    }

    inline const TConfig& GetConfig() const
    {
        return Config;
    }
};

template <class TClientType, class TConfigType>
class TCommonSearchServer: public TSearchServerAbstract<TConfigType> {
public:
    typedef TCommonSearchServer<TClientType,TConfigType> TServer;
    inline TCommonSearchServer(const TConfigType& config)
        : TSearchServerAbstract<TConfigType>(config)
    {
    }

    virtual TClientRequest* CreateClient() {
        return new TClientType;
    }

};
