// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <condition_variable>
#include <mutex>
#include <thread>
#include <tuple>
#include <unordered_map>
#include <vector>
#include "bandwidth.h"
#include "internal_list.h"
#include "node_id.h"
#include "optional.h"
#include "timer.h"
#include "trace.h"

#include <iostream>

namespace overnet {
namespace routing_table_impl {

struct FullLinkLabel {
  NodeId from;
  NodeId to;
  uint64_t link_label;
};

inline bool operator==(const FullLinkLabel& a, const FullLinkLabel& b) {
  return a.from == b.from && a.to == b.to && a.link_label == b.link_label;
}

}  // namespace routing_table_impl
}  // namespace overnet

namespace std {
template <>
struct hash<overnet::routing_table_impl::FullLinkLabel> {
  size_t operator()(
      const overnet::routing_table_impl::FullLinkLabel& id) const {
    return id.from.Hash() ^ id.to.Hash() ^ id.link_label;
  }
};
}  // namespace std

namespace overnet {

enum class LinkMedia : uint8_t {
  Unknown,
  Wired,
  Wireless,
  Internet,
};

static constexpr uint64_t METRIC_VERSION_TOMBSTONE = ~uint64_t(0);

class LinkMetrics {
 public:
  LinkMetrics(NodeId from, NodeId to, uint64_t version, uint64_t link_label)
      : from_(from), to_(to), version_(version), link_label_(link_label) {}

  NodeId from() const { return from_; }
  NodeId to() const { return to_; }
  uint64_t version() const { return version_; }
  uint64_t link_label() const { return link_label_; }
  Bandwidth bw_link() const { return bw_link_; }
  Bandwidth bw_used() const { return bw_used_; }
  TimeDelta rtt() const { return rtt_; }
  LinkMedia media() const { return media_; }
  uint32_t mss() const { return mss_; }

  void set_bw_link(Bandwidth x) { bw_link_ = x; }
  void set_bw_used(Bandwidth x) { bw_used_ = x; }
  void set_rtt(TimeDelta x) { rtt_ = x; }
  void set_media(LinkMedia x) { media_ = x; }
  void set_mss(uint32_t x) { mss_ = x; }

 private:
  NodeId from_;
  NodeId to_;
  uint64_t version_;
  uint64_t link_label_;
  Bandwidth bw_link_{Bandwidth::Zero()};
  Bandwidth bw_used_{Bandwidth::Zero()};
  TimeDelta rtt_{TimeDelta::PositiveInf()};
  LinkMedia media_{LinkMedia::Unknown};
  uint32_t mss_{std::numeric_limits<uint32_t>::max()};
};

std::ostream& operator<<(std::ostream& out, const LinkMetrics& m);

class NodeMetrics {
 public:
  NodeMetrics(NodeId node_id, uint64_t version)
      : node_id_(node_id), version_(version) {}

  NodeId node_id() const { return node_id_; }
  uint64_t version() const { return version_; }
  uint8_t battery_pct() const { return battery_pct_; }
  TimeDelta forwarding_time() const { return forwarding_time_; }

  void set_battery_pct(uint8_t battery_pct) { battery_pct_ = battery_pct; }
  void set_forwarding_time(TimeDelta forwarding_time) {
    forwarding_time_ = forwarding_time;
  }

 private:
  NodeId node_id_;
  uint64_t version_;
  uint8_t battery_pct_ = 100;
  TimeDelta forwarding_time_{TimeDelta::PositiveInf()};
};

std::ostream& operator<<(std::ostream& out, const LinkMetrics& m);

class RoutingTable {
 public:
  RoutingTable(NodeId root_node, Timer* timer, TraceSink trace_sink,
               bool allow_threading)
      : root_node_(root_node),
        timer_(timer),
        trace_sink_(trace_sink),
        allow_threading_(allow_threading) {}
  ~RoutingTable();

  static constexpr TimeDelta EntryExpiry() { return TimeDelta::FromMinutes(5); }

  struct SelectedLink {
    uint64_t link_id;
    uint32_t route_mss;

    bool operator==(SelectedLink other) const {
      return link_id == other.link_id && route_mss == other.route_mss;
    }
  };
  using SelectedLinks = std::unordered_map<NodeId, SelectedLink>;

  void Update(std::vector<NodeMetrics> node_metrics,
              std::vector<LinkMetrics> link_metrics, bool flush_old_nodes);

  // Returns true if this update concludes any changes begun by all prior
  // Update() calls.
  template <class F>
  bool PollLinkUpdates(F f) {
    if (!mu_.try_lock()) {
      return false;
    }
    if (selected_links_version_ != published_links_version_) {
      published_links_version_ = selected_links_version_;
      f(selected_links_);
    }
    const bool done = !processing_changes_.has_value();
    mu_.unlock();
    return done;
  }

  void BlockUntilNoBackgroundUpdatesProcessing() {
    std::unique_lock<std::mutex> lock(mu_);
    cv_.wait(lock, [this]() -> bool { return !processing_changes_; });
  }

 private:
  const NodeId root_node_;
  Timer* const timer_;
  const TraceSink trace_sink_;

  struct Metrics {
    std::vector<NodeMetrics> node_metrics;
    std::vector<LinkMetrics> link_metrics;
    bool Empty() const { return node_metrics.empty() && link_metrics.empty(); }
    void Clear() {
      node_metrics.clear();
      link_metrics.clear();
    }
  };
  Metrics change_log_;
  const bool allow_threading_;
  bool flush_requested_ = false;

  void ApplyChanges(TimeStamp now, const Metrics& changes, bool flush);
  SelectedLinks BuildForwardingTable();

  TimeStamp last_update_{TimeStamp::Epoch()};
  uint64_t path_finding_run_ = 0;

  std::mutex mu_;
  std::condition_variable cv_;
  Optional<std::thread> processing_changes_;

  struct Node;

  struct Link {
    Link(TimeStamp now, LinkMetrics initial_metrics, Node* to)
        : metrics(initial_metrics), last_updated(now), to_node(to) {}
    LinkMetrics metrics;
    TimeStamp last_updated;
    InternalListNode<Link> outgoing_link;
    Node* const to_node;
  };

  struct Node {
    Node(TimeStamp now, NodeMetrics initial_metrics)
        : metrics(initial_metrics), last_updated(now) {}
    NodeMetrics metrics;
    TimeStamp last_updated;
    InternalList<Link, &Link::outgoing_link> outgoing_links;

    // Path finding temporary state.
    uint64_t last_path_finding_run = 0;
    TimeDelta best_rtt{TimeDelta::Zero()};
    Node* best_from;
    Link* best_link;
    uint32_t mss;
    bool queued = false;
    InternalListNode<Node> path_finding_node;
  };

  void RemoveOutgoingLinks(Node& node);

  std::unordered_map<NodeId, Node> node_metrics_;
  std::unordered_map<routing_table_impl::FullLinkLabel, Link> link_metrics_;

  uint64_t selected_links_version_ = 0;
  SelectedLinks selected_links_;
  uint64_t published_links_version_ = 0;
};

}  // namespace overnet
