#pragma once

#include <drogon/HttpController.h>
#include "server.hpp"

namespace simple_object_storage {

class HttpController : public drogon::HttpController<HttpController> {
public:
    METHOD_LIST_BEGIN
    ADD_METHOD_TO(HttpController::getIndex, "/index.html", {drogon::Get});
    ADD_METHOD_TO(HttpController::getHash, "/hash/{1}", {drogon::Get});
    ADD_METHOD_TO(HttpController::getVersion, "/version/{1}", {drogon::Get});
    ADD_METHOD_TO(HttpController::checkExists, "/exists/{1}", {drogon::Get});
    ADD_METHOD_TO(HttpController::getDirectory, "/dir", {drogon::Get});
    ADD_METHOD_TO(HttpController::uploadObject, "/upload", {drogon::Put});
    ADD_METHOD_TO(HttpController::updateObject, "/update", {drogon::Put});
    ADD_METHOD_TO(HttpController::getMetadata, "/meta/{1}", {drogon::Get});
    ADD_METHOD_TO(HttpController::deleteObject, "/deleteobject", {drogon::Get});
    ADD_METHOD_TO(HttpController::deleteOldObjects, "/deleteoldobjects", {drogon::Get});
    ADD_METHOD_TO(HttpController::getStatus, "/status", {drogon::Get});
    ADD_METHOD_TO(HttpController::getObject, "/object/{1}", {drogon::Get});
    ADD_METHOD_TO(HttpController::getRoot, "/", {drogon::Get});
    ADD_METHOD_TO(HttpController::getAny, "/{1}", {drogon::Get});
    METHOD_LIST_END

    void getIndex(const drogon::HttpRequestPtr &req,
                  std::function<void(const drogon::HttpResponsePtr &)> &&callback);
    
    void getHash(const drogon::HttpRequestPtr &req,
                 std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                 const std::string &key);
    
    void getVersion(const drogon::HttpRequestPtr &req,
                    std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                    const std::string &key);
    
    void checkExists(const drogon::HttpRequestPtr &req,
                     std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                     const std::string &key);
    
    void getDirectory(const drogon::HttpRequestPtr &req,
                      std::function<void(const drogon::HttpResponsePtr &)> &&callback);
    
    void uploadObject(const drogon::HttpRequestPtr &req,
                      std::function<void(const drogon::HttpResponsePtr &)> &&callback);
    
    void updateObject(const drogon::HttpRequestPtr &req,
                      std::function<void(const drogon::HttpResponsePtr &)> &&callback);
    
    void getMetadata(const drogon::HttpRequestPtr &req,
                     std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                     const std::string &key);
    
    void deleteObject(const drogon::HttpRequestPtr &req,
                      std::function<void(const drogon::HttpResponsePtr &)> &&callback);

    void deleteOldObjects(const drogon::HttpRequestPtr &req,
                          std::function<void(const drogon::HttpResponsePtr &)> &&callback);

    void getStatus(const drogon::HttpRequestPtr &req,
                   std::function<void(const drogon::HttpResponsePtr &)> &&callback);
    
    void getObject(const drogon::HttpRequestPtr &req,
                   std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                   const std::string &key);
    
    void getRoot(const drogon::HttpRequestPtr &req,
                 std::function<void(const drogon::HttpResponsePtr &)> &&callback);
    
    void getAny(const drogon::HttpRequestPtr &req,
                std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                const std::string &path);
};

} // namespace simple_object_storage