#pragma once
#include <drogon/DrObject.h>
#include <drogon/utils/HttpConstraint.h>
#include <drogon/HttpAppFramework.h>
#include <trantor/utils/Logger.h>
#include <iostream>
#include <string>
#include <vector>
#define PATH_LIST_BEGIN           \
    static void initPathRouting() \
    {
#define PATH_ADD(path, ...) registerSelf__(path, {__VA_ARGS__})
#define PATH_LIST_END }
namespace drogon
{
class HttpSimpleControllerBase : public virtual DrObjectBase
{
  public:
    virtual void asyncHandleHttpRequest(
        const HttpRequestPtr &req,
        std::function<void(const HttpResponsePtr &)> &&callback) = 0;
    virtual ~HttpSimpleControllerBase()
    {
    }
};
template <typename T, bool AutoCreation = true>
class HttpSimpleController : public DrObject<T>, public HttpSimpleControllerBase
{
  public:
    static const bool isAutoCreation = AutoCreation;
    virtual ~HttpSimpleController()
    {
    }
  protected:
    HttpSimpleController()
    {
    }
    static void registerSelf__(
        const std::string &path,
        const std::vector<internal::HttpConstraint> &constraints)
    {
        LOG_TRACE << "register simple controller("
                  << HttpSimpleController<T, AutoCreation>::classTypeName()
                  << ") on path:" << path;
        app().registerHttpSimpleController(
            path,
            HttpSimpleController<T, AutoCreation>::classTypeName(),
            constraints);
    }
  private:
    class pathRegistrator
    {
      public:
        pathRegistrator()
        {
            if (AutoCreation)
            {
                T::initPathRouting();
            }
        }
    };
    friend pathRegistrator;
    static pathRegistrator registrator_;
    virtual void *touch()
    {
        return &registrator_;
    }
};
template <typename T, bool AutoCreation>
typename HttpSimpleController<T, AutoCreation>::pathRegistrator
    HttpSimpleController<T, AutoCreation>::registrator_;
}  