#ifndef FILESERVER_SERVER_HXX
#define FILESERVER_SERVER_HXX

#include <corvusoft/restbed/service.hpp>
#include "mrpc/fileserver.hxx"
#include "../data/data.hxx"

extern std::shared_ptr<restbed::Service> g_service;

struct Server final : public mrpc::MRPCServer, public Data {
    explicit Server(std::shared_ptr<restbed::Resource> &ptr) : MRPCServer(ptr), Data() {}

    std::shared_ptr<Token> get_token(const std::string&);
    std::shared_ptr<User> is_token_valid(const std::string&);
    std::shared_ptr<User> get_user(std::uint64_t id);

    static void delete_node(const std::shared_ptr<User> &user, std::uint64_t id, const std::function<void(std::string)>& log);
    void logout_user(std::uint64_t id);
    void delete_user(const std::shared_ptr<User> &user);
    void send_tfa_mail(const std::shared_ptr<User> &user);
    static bool check_tfa_code(const std::shared_ptr<User> &user, const std::string &code);
    bool check_mail_code(const std::shared_ptr<User> &user, const std::string &code);
    void send_mail(const std::string& email, const std::string& title, const std::string& body);
    std::uint64_t nodes_size(const std::shared_ptr<User> &user, const std::vector<std::uint64_t> &ids);

    void download(const std::shared_ptr<restbed::Session>&);
    void download_multi(const std::shared_ptr<restbed::Session>&);
    void upload(const std::shared_ptr<restbed::Session>&);


private:
    std::optional<std::string> Auth_signup(std::string &&username, std::string &&password) override;
    mrpc::Response<mrpc::LoginResponse> Auth_login(std::string &&username, std::string &&password, std::optional<std::string> &&otp) override;
    void Auth_send_recovery_key(std::string &&username) override;
    std::optional<std::string> Auth_reset_password(std::string &&key, std::string &&password) override;
    std::optional<std::string> Auth_change_password(std::string &&token, std::string &&old_pw, std::string &&new_pw) override;
    void Auth_logout(std::string &&token) override;
    std::optional<std::string> Auth_logout_all(std::string &&token) override;
    std::optional<std::string> Auth_tfa_setup_mail(std::string &&token) override;
    mrpc::Response<std::string> Auth_tfa_setup_totp(std::string &&token) override;
    std::optional<std::string> Auth_tfa_complete(std::string &&token, std::string &&otp) override;
    std::optional<std::string> Auth_tfa_disable(std::string &&token) override;
    std::optional<std::string> Auth_delete_user(std::string &&token) override;
    mrpc::Response<mrpc::Session> Auth_session_info(std::string &&token) override;

    mrpc::Response<std::vector<mrpc::UserInfo>> Admin_list_users(std::string &&token) override;
    std::optional<std::string> Admin_delete_user(std::string &&token, std::uint64_t &&user) override;
    std::optional<std::string> Admin_logout(std::string &&token, std::uint64_t &&user) override;
    std::optional<std::string> Admin_disable_tfa(std::string &&token, std::uint64_t &&user) override;
    std::optional<std::string> Admin_set_admin(std::string &&token, std::uint64_t &&user, bool &&admin) override;
    std::optional<std::string> Admin_set_enabled(std::string &&token, std::uint64_t &&user, bool &&enabled) override;
    std::optional<std::string> Admin_sudo(std::string &&token, std::uint64_t &&user) override;
    std::optional<std::string> Admin_unsudo(std::string &&token) override;
    std::optional<std::string> Admin_shutdown(std::string &&token) override;

    mrpc::Response<mrpc::Node> FS_get_node(std::string &&token, std::uint64_t &&node) override;
    mrpc::Response<std::vector<mrpc::PathSegment>> FS_get_path(std::string &&token, std::uint64_t &&node) override;
    mrpc::Response<std::uint64_t> FS_get_nodes_size(std::string &&token, std::vector<std::uint64_t> &&nodes) override;
    mrpc::Response<mrpc::CreateNodeInfo> FS_create_node(std::string &&token, bool &&file, std::uint64_t &&parent, std::string &&name) override;
    std::optional<std::string> FS_move_nodes(std::string &&token, std::vector<std::uint64_t> &&nodes, std::uint64_t &&parent) override;
    void FS_delete_nodes(std::string &&token, std::vector<std::uint64_t> &&nodes, mrpc::MRPCStream<std::string> &&stream) override;
    mrpc::Response<std::string> FS_download_preview(std::string &&token, std::uint64_t &&node) override;
    mrpc::Response<std::string> FS_get_mime(std::string &&token, std::uint64_t &&node) override;
};

#endif //FILESERVER_SERVER_HXX
