#pragma once

#include <xrpld/overlay/Message.h>

#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/net/IPEndpoint.h>
#include <xrpl/json/json_value.h>
#include <xrpl/protocol/PublicKey.h>

namespace xrpl {

namespace Resource {
class Charge;
}

enum class ProtocolFeature {
    ValidatorListPropagation,
    ValidatorList2Propagation,
    LedgerReplay,
};

/** Represents a peer connection in the overlay. */
class Peer
{
public:
    using ptr = std::shared_ptr<Peer>;

    /** Uniquely identifies a peer.
        This can be stored in tables to find the peer later. Callers
        can discover if the peer is no longer connected and make
        adjustments as needed.
    */
    using id_t = std::uint32_t;

    virtual ~Peer() = default;

    //
    // Network
    //

    virtual void
    send(std::shared_ptr<Message> const& m) = 0;

    virtual beast::IP::Endpoint
    getRemoteAddress() const = 0;

    /** Send aggregated transactions' hashes. */
    virtual void
    sendTxQueue() = 0;

    /** Aggregate transaction's hash. */
    virtual void
    addTxQueue(uint256 const&) = 0;

    /** Remove hash from the transactions' hashes queue. */
    virtual void
    removeTxQueue(uint256 const&) = 0;

    /** Adjust this peer's load balance based on the type of load imposed. */
    virtual void
    charge(Resource::Charge const& fee, std::string const& context) = 0;

    //
    // Identity
    //

    virtual id_t
    id() const = 0;

    /** Returns `true` if this connection is a member of the cluster. */
    virtual bool
    cluster() const = 0;

    virtual bool
    isHighLatency() const = 0;

    virtual int
    getScore(bool) const = 0;

    virtual PublicKey const&
    getNodePublic() const = 0;

    virtual Json::Value
    json() = 0;

    virtual bool
    supportsFeature(ProtocolFeature f) const = 0;

    virtual std::optional<std::size_t>
    publisherListSequence(PublicKey const&) const = 0;

    virtual void
    setPublisherListSequence(PublicKey const&, std::size_t const) = 0;

    virtual std::string const&
    fingerprint() const = 0;
    //
    // Ledger
    //

    virtual uint256 const&
    getClosedLedgerHash() const = 0;
    virtual bool
    hasLedger(uint256 const& hash, std::uint32_t seq) const = 0;
    virtual void
    ledgerRange(std::uint32_t& minSeq, std::uint32_t& maxSeq) const = 0;
    virtual bool
    hasTxSet(uint256 const& hash) const = 0;
    virtual void
    cycleStatus() = 0;
    virtual bool
    hasRange(std::uint32_t uMin, std::uint32_t uMax) = 0;

    virtual bool
    compressionEnabled() const = 0;

    virtual bool
    txReduceRelayEnabled() const = 0;
};

}  // namespace xrpl
