#pragma once

#include <Wt/Auth/AbstractUserDatabase>

namespace eedb::db {
class PgConnection;
}

namespace Wt {
class WEnviroment;
}

namespace Wt::Auth {
class AuthService;
}

namespace eedb::auth {

class PgUserAuth : public Wt::Auth::AbstractUserDatabase {
  public:
    void setAuthService(Wt::Auth::AuthService * s) {
        _authService = s;
    }

    virtual ~PgUserAuth();
    PgUserAuth(eedb::db::PgConnection & db, const Wt::WEnvironment & env);

    Transaction * startTransaction() override;

    Wt::Auth::User findWithId(const std::string & id) const override;
    Wt::Auth::User findWithIdentity(const std::string & provider, const Wt::WString & identity) const override;
    Wt::Auth::User findWithEmailToken(const std::string & hash) const override;
    Wt::Auth::User findWithEmail(const std::string & address) const override;

    void addIdentity(const Wt::Auth::User & user, const std::string & provider, const Wt::WString & id) override;
    void setIdentity(const Wt::Auth::User & user, const std::string & provider, const Wt::WString & id) override;
    Wt::WString identity(const Wt::Auth::User & user, const std::string & provider) const override;
    void removeIdentity(const Wt::Auth::User & user, const std::string & provider) override;

    Wt::Auth::User registerNew() override;
    void deleteUser(const Wt::Auth::User & user) override;

    void setPassword(const Wt::Auth::User & user, const Wt::Auth::PasswordHash & password) override;
    Wt::Auth::PasswordHash password(const Wt::Auth::User & user) const override;

    bool setEmail(const Wt::Auth::User & user, const std::string & address) override;
    std::string email(const Wt::Auth::User & user) const override;
    void setUnverifiedEmail(const Wt::Auth::User & user, const std::string & address) override;
    std::string unverifiedEmail(const Wt::Auth::User & user) const override;

    void setEmailToken(const Wt::Auth::User & user, const Wt::Auth::Token & token, Wt::Auth::User::EmailTokenRole role) override;
    Wt::Auth::Token emailToken(const Wt::Auth::User & user) const override;
    Wt::Auth::User::EmailTokenRole emailTokenRole(const Wt::Auth::User & user) const override;

    void addAuthToken(const Wt::Auth::User & user, const Wt::Auth::Token & token) override;
    void removeAuthToken(const Wt::Auth::User &, const std::string & hash) override;
    Wt::Auth::User findWithAuthToken(const std::string & hash) const override;
    int updateAuthToken(const Wt::Auth::User & user, const std::string & oldhash, const std::string & newhash) override;

    void setFailedLoginAttempts(const Wt::Auth::User & user, int count) override;
    int failedLoginAttempts(const Wt::Auth::User & user) const override;
    void setLastLoginAttempt(const Wt::Auth::User & user, const Wt::WDateTime & t) override;
    Wt::WDateTime lastLoginAttempt(const Wt::Auth::User & user) const override;
	
	void logout(const Wt::Auth::User & user);

  private:
    eedb::db::PgConnection & db;
    const Wt::WEnvironment & _env;
    const Wt::Auth::AuthService * _authService;
};
}
