#ifndef SRC_NODE_SOCKADDR_H_
#define SRC_NODE_SOCKADDR_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "env.h"
#include "memory_tracker.h"
#include "base_object.h"
#include "node.h"
#include "node_worker.h"
#include "uv.h"
#include "v8.h"

#include <memory>
#include <string>
#include <list>
#include <unordered_map>

namespace node {

class Environment;

class SocketAddress : public MemoryRetainer {
 public:
  enum class CompareResult {
    NOT_COMPARABLE = -2,
    LESS_THAN,
    SAME,
    GREATER_THAN
  };

  struct Hash {
    size_t operator()(const SocketAddress& addr) const;
  };

  inline bool operator==(const SocketAddress& other) const;
  inline bool operator!=(const SocketAddress& other) const;

  inline bool operator<(const SocketAddress& other) const;
  inline bool operator>(const SocketAddress& other) const;
  inline bool operator<=(const SocketAddress& other) const;
  inline bool operator>=(const SocketAddress& other) const;

  inline static bool is_numeric_host(const char* hostname);
  inline static bool is_numeric_host(const char* hostname, int family);

  // Returns true if converting {family, host, port} to *addr succeeded.
  static bool ToSockAddr(
      int32_t family,
      const char* host,
      uint32_t port,
      sockaddr_storage* addr);

  // Returns true if converting {family, host, port} to *addr succeeded.
  static bool New(
      int32_t family,
      const char* host,
      uint32_t port,
      SocketAddress* addr);

  static bool New(
      const char* host,
      uint32_t port,
      SocketAddress* addr);

  // Returns the port for an IPv4 or IPv6 address.
  inline static int GetPort(const sockaddr* addr);
  inline static int GetPort(const sockaddr_storage* addr);

  // Returns the numeric host as a string for an IPv4 or IPv6 address.
  inline static std::string GetAddress(const sockaddr* addr);
  inline static std::string GetAddress(const sockaddr_storage* addr);

  // Returns the struct length for an IPv4, IPv6 or UNIX domain.
  inline static size_t GetLength(const sockaddr* addr);
  inline static size_t GetLength(const sockaddr_storage* addr);

  SocketAddress() = default;

  inline explicit SocketAddress(const sockaddr* addr);
  inline SocketAddress(const SocketAddress& addr);
  inline SocketAddress& operator=(const sockaddr* other);
  inline SocketAddress& operator=(const SocketAddress& other);

  inline const sockaddr& operator*() const;
  inline const sockaddr* operator->() const;

  inline const sockaddr* data() const;
  inline const uint8_t* raw() const;
  inline sockaddr* storage();
  inline size_t length() const;

  inline int family() const;
  inline std::string address() const;
  inline int port() const;

  // Returns true if the given other SocketAddress is a match
  // for this one. The addresses are a match if:
  // 1. They are the same family and match identically
  // 2. They are different family but match semantically (
  //     for instance, an IPv4 address in IPv6 notation)
  bool is_match(const SocketAddress& other) const;

  // Compares this SocketAddress to the given other SocketAddress.
  CompareResult compare(const SocketAddress& other) const;

  // Returns true if this SocketAddress is within the subnet
  // identified by the given network address and CIDR prefix.
  bool is_in_network(const SocketAddress& network, int prefix) const;

  // If the SocketAddress is an IPv6 address, returns the
  // current value of the IPv6 flow label, if set. Otherwise
  // returns 0.
  inline uint32_t flow_label() const;

  // If the SocketAddress is an IPv6 address, sets the
  // current value of the IPv6 flow label. If not an
  // IPv6 address, set_flow_label is a non-op. It
  // is important to note that the flow label,
  // while represented as an uint32_t, the flow
  // label is strictly limited to 20 bits, and
  // this will assert if any value larger than
  // 20-bits is specified.
  inline void set_flow_label(uint32_t label = 0);

  inline void Update(uint8_t* data, size_t len);
  inline void Update(const sockaddr* data, size_t len);

  static SocketAddress FromSockName(const uv_udp_t& handle);
  static SocketAddress FromSockName(const uv_tcp_t& handle);
  static SocketAddress FromPeerName(const uv_udp_t& handle);
  static SocketAddress FromPeerName(const uv_tcp_t& handle);

  inline v8::MaybeLocal<v8::Object> ToJS(
      Environment* env,
      v8::Local<v8::Object> obj = v8::Local<v8::Object>()) const;

  inline std::string ToString() const;

  SET_NO_MEMORY_INFO()
  SET_MEMORY_INFO_NAME(SocketAddress)
  SET_SELF_SIZE(SocketAddress)

  template <typename T>
  using Map = std::unordered_map<SocketAddress, T, Hash>;

 private:
  sockaddr_storage address_;
};

class SocketAddressBase : public BaseObject {
 public:
  static bool HasInstance(Environment* env, v8::Local<v8::Value> value);
  static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
      Environment* env);
  static void Initialize(Environment* env, v8::Local<v8::Object> target);
  static BaseObjectPtr<SocketAddressBase> Create(
      Environment* env,
      std::shared_ptr<SocketAddress> address);

  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void Detail(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void LegacyDetail(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void GetFlowLabel(const v8::FunctionCallbackInfo<v8::Value>& args);

  SocketAddressBase(
    Environment* env,
    v8::Local<v8::Object> wrap,
    std::shared_ptr<SocketAddress> address);

  inline const std::shared_ptr<SocketAddress>& address() const {
    return address_;
  }

  void MemoryInfo(MemoryTracker* tracker) const override;
  SET_MEMORY_INFO_NAME(SocketAddressBase)
  SET_SELF_SIZE(SocketAddressBase)

  TransferMode GetTransferMode() const override {
    return TransferMode::kCloneable;
  }
  std::unique_ptr<worker::TransferData> CloneForMessaging() const override;

  class TransferData : public worker::TransferData {
   public:
    inline explicit TransferData(const SocketAddressBase* wrap)
        : address_(wrap->address_) {}

    inline explicit TransferData(std::shared_ptr<SocketAddress> address)
        : address_(std::move(address)) {}

    BaseObjectPtr<BaseObject> Deserialize(
        Environment* env,
        v8::Local<v8::Context> context,
        std::unique_ptr<worker::TransferData> self) override;

    void MemoryInfo(MemoryTracker* tracker) const override;
    SET_MEMORY_INFO_NAME(SocketAddressBase::TransferData)
    SET_SELF_SIZE(TransferData)

   private:
    std::shared_ptr<SocketAddress> address_;
  };

 private:
  std::shared_ptr<SocketAddress> address_;
};

template <typename T>
class SocketAddressLRU : public MemoryRetainer {
 public:
  using Type = typename T::Type;

  inline explicit SocketAddressLRU(size_t max_size);

  // If the item already exists, returns a reference to
  // the existing item, adjusting items position in the
  // LRU. If the item does not exist, emplaces the item
  // and returns the new item.
  Type* Upsert(const SocketAddress& address);

  // Returns a reference to the item if it exists, or
  // nullptr. The position in the LRU is not modified.
  Type* Peek(const SocketAddress& address) const;

  size_t size() const { return map_.size(); }
  size_t max_size() const { return max_size_; }

  void MemoryInfo(MemoryTracker* tracker) const override;
  SET_MEMORY_INFO_NAME(SocketAddressLRU)
  SET_SELF_SIZE(SocketAddressLRU)

 private:
  using Pair = std::pair<SocketAddress, Type>;
  using Iterator = typename std::list<Pair>::iterator;

  void CheckExpired();

  std::list<Pair> list_;
  SocketAddress::Map<Iterator> map_;
  size_t max_size_;
};

// A BlockList is used to evaluate whether a given
// SocketAddress should be accepted for inbound or
// outbound network activity.
class SocketAddressBlockList : public MemoryRetainer {
 public:
  explicit SocketAddressBlockList(
      std::shared_ptr<SocketAddressBlockList> parent = {});
  ~SocketAddressBlockList() = default;

  void AddSocketAddress(const std::shared_ptr<SocketAddress>& address);

  void RemoveSocketAddress(const std::shared_ptr<SocketAddress>& address);

  void AddSocketAddressRange(
      const std::shared_ptr<SocketAddress>& start,
      const std::shared_ptr<SocketAddress>& end);

  void AddSocketAddressMask(
      const std::shared_ptr<SocketAddress>& address,
      int prefix);

  bool Apply(const std::shared_ptr<SocketAddress>& address);

  size_t size() const { return rules_.size(); }

  v8::MaybeLocal<v8::Array> ListRules(Environment* env);

  struct Rule : public MemoryRetainer {
    virtual bool Apply(const std::shared_ptr<SocketAddress>& address) = 0;
    inline v8::MaybeLocal<v8::Value> ToV8String(Environment* env);
    virtual std::string ToString() = 0;
  };

  struct SocketAddressRule final : Rule {
    std::shared_ptr<SocketAddress> address;

    explicit SocketAddressRule(const std::shared_ptr<SocketAddress>& address);

    bool Apply(const std::shared_ptr<SocketAddress>& address) override;
    std::string ToString() override;

    void MemoryInfo(node::MemoryTracker* tracker) const override;
    SET_MEMORY_INFO_NAME(SocketAddressRule)
    SET_SELF_SIZE(SocketAddressRule)
  };

  struct SocketAddressRangeRule final : Rule {
    std::shared_ptr<SocketAddress> start;
    std::shared_ptr<SocketAddress> end;

    SocketAddressRangeRule(
        const std::shared_ptr<SocketAddress>& start,
        const std::shared_ptr<SocketAddress>& end);

    bool Apply(const std::shared_ptr<SocketAddress>& address) override;
    std::string ToString() override;

    void MemoryInfo(node::MemoryTracker* tracker) const override;
    SET_MEMORY_INFO_NAME(SocketAddressRangeRule)
    SET_SELF_SIZE(SocketAddressRangeRule)
  };

  struct SocketAddressMaskRule final : Rule {
    std::shared_ptr<SocketAddress> network;
    int prefix;

    SocketAddressMaskRule(
        const std::shared_ptr<SocketAddress>& address,
        int prefix);

    bool Apply(const std::shared_ptr<SocketAddress>& address) override;
    std::string ToString() override;

    void MemoryInfo(node::MemoryTracker* tracker) const override;
    SET_MEMORY_INFO_NAME(SocketAddressMaskRule)
    SET_SELF_SIZE(SocketAddressMaskRule)
  };

  void MemoryInfo(node::MemoryTracker* tracker) const override;
  SET_MEMORY_INFO_NAME(SocketAddressBlockList)
  SET_SELF_SIZE(SocketAddressBlockList)

 private:
  bool ListRules(
      Environment* env,
      std::vector<v8::Local<v8::Value>>* vec);

  std::shared_ptr<SocketAddressBlockList> parent_;
  std::list<std::unique_ptr<Rule>> rules_;
  SocketAddress::Map<std::list<std::unique_ptr<Rule>>::iterator> address_rules_;

  Mutex mutex_;
};

class SocketAddressBlockListWrap : public BaseObject {
 public:
  static bool HasInstance(Environment* env, v8::Local<v8::Value> value);
  static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
      Environment* env);
  static void Initialize(v8::Local<v8::Object> target,
                         v8::Local<v8::Value> unused,
                         v8::Local<v8::Context> context,
                         void* priv);

  static BaseObjectPtr<SocketAddressBlockListWrap> New(Environment* env);
  static BaseObjectPtr<SocketAddressBlockListWrap> New(
      Environment* env,
      std::shared_ptr<SocketAddressBlockList> blocklist);

  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void AddAddress(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void AddRange(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void AddSubnet(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void Check(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void GetRules(const v8::FunctionCallbackInfo<v8::Value>& args);

  SocketAddressBlockListWrap(
      Environment* env,
      v8::Local<v8::Object> wrap,
      std::shared_ptr<SocketAddressBlockList> blocklist =
          std::make_shared<SocketAddressBlockList>());

  void MemoryInfo(node::MemoryTracker* tracker) const override;
  SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap)
  SET_SELF_SIZE(SocketAddressBlockListWrap)

  TransferMode GetTransferMode() const override {
    return TransferMode::kCloneable;
  }
  std::unique_ptr<worker::TransferData> CloneForMessaging() const override;

  class TransferData : public worker::TransferData {
   public:
    inline explicit TransferData(const SocketAddressBlockListWrap* wrap)
        : blocklist_(wrap->blocklist_) {}

    inline explicit TransferData(
        std::shared_ptr<SocketAddressBlockList> blocklist)
        : blocklist_(std::move(blocklist)) {}

    BaseObjectPtr<BaseObject> Deserialize(
        Environment* env,
        v8::Local<v8::Context> context,
        std::unique_ptr<worker::TransferData> self) override;

    void MemoryInfo(MemoryTracker* tracker) const override;
    SET_MEMORY_INFO_NAME(SocketAddressBlockListWrap::TransferData)
    SET_SELF_SIZE(TransferData)

   private:
    std::shared_ptr<SocketAddressBlockList> blocklist_;
  };

 private:
  std::shared_ptr<SocketAddressBlockList> blocklist_;
};

}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#endif  // SRC_NODE_SOCKADDR_H_
