// 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.

#include "src/connectivity/overnet/overnetstack/mdns.h"

#include <fbl/ref_counted.h>
#include <fuchsia/net/mdns/cpp/fidl.h>

#include "garnet/public/lib/fostr/fidl/fuchsia/net/mdns/formatting.h"
#include "src/connectivity/overnet/lib/labels/node_id.h"
#include "src/connectivity/overnet/overnetstack/fuchsia_port.h"

namespace overnetstack {

static const char* kServiceName = "_temp_overnet._udp.";

static fuchsia::net::mdns::SubscriberPtr ConnectToSubscriber(
    sys::ComponentContext* component_context, const char* why) {
  auto svc =
      component_context->svc()->Connect<fuchsia::net::mdns::Subscriber>();
  svc.set_error_handler([why](zx_status_t status) {
    OVERNET_TRACE(ERROR) << why << " mdns subscriber failure: "
                         << zx_status_get_string(status);
  });
  return svc;
}

static fuchsia::net::mdns::PublisherPtr ConnectToPublisher(
    sys::ComponentContext* component_context, const char* why) {
  auto svc = component_context->svc()->Connect<fuchsia::net::mdns::Publisher>();
  svc.set_error_handler([why](zx_status_t status) {
    OVERNET_TRACE(ERROR) << why << " mdns publisher failure: "
                         << zx_status_get_string(status);
  });
  return svc;
}

class MdnsIntroducer::Impl : public fbl::RefCounted<MdnsIntroducer>,
                             public fuchsia::net::mdns::ServiceSubscriber {
 public:
  Impl(UdpNub* nub) : nub_(nub), subscriber_binding_(this) {}

  void Begin(sys::ComponentContext* component_context) {
    std::cerr << "Querying mDNS for overnet services [" << kServiceName
              << "]\n";
    auto svc = ConnectToSubscriber(component_context, "Introducer");
    fidl::InterfaceHandle<fuchsia::net::mdns::ServiceSubscriber>
        subscriber_handle;

    subscriber_binding_.Bind(subscriber_handle.NewRequest());
    subscriber_binding_.set_error_handler([this](zx_status_t status) {
      subscriber_binding_.set_error_handler(nullptr);
      subscriber_binding_.Unbind();
    });

    svc->SubscribeToService(kServiceName, std::move(subscriber_handle));
  }

 private:
  void HandleDiscoverOrUpdate(const fuchsia::net::mdns::ServiceInstance& svc,
                              bool update) {
    if (svc.service != kServiceName) {
      std::cout << "Unexpected service name (ignored): " << svc.service << "\n";
      return;
    }
    auto parsed_instance_name = overnet::NodeId::FromString(svc.instance);
    if (parsed_instance_name.is_error()) {
      std::cout << "Failed to parse instance name: "
                << parsed_instance_name.AsStatus() << "\n";
      return;
    }
    auto instance_id = *parsed_instance_name.get();

    std::vector<overnet::IpAddr> addrs;
    for (const auto& endpoint : svc.endpoints) {
      auto status = ToIpAddr(endpoint);
      if (status.is_error()) {
        std::cout << "Failed to convert address: " << status << "\n";
      } else {
        addrs.emplace_back(std::move(*status));
      }
    }

    nub_->Initiate(std::move(addrs), instance_id);
  }

  static overnet::StatusOr<overnet::IpAddr> ToIpAddr(
      const fuchsia::net::Endpoint& endpoint) {
    const fuchsia::net::IpAddress& net_addr = endpoint.addr;
    overnet::IpAddr udp_addr;
    memset(&udp_addr, 0, sizeof(udp_addr));
    switch (net_addr.Which()) {
      case fuchsia::net::IpAddress::Tag::Invalid:
        return overnet::Status(overnet::StatusCode::INVALID_ARGUMENT,
                               "unknown address type");
      case fuchsia::net::IpAddress::Tag::kIpv4:
        if (!net_addr.is_ipv4()) {
          return overnet::Status(overnet::StatusCode::INVALID_ARGUMENT,
                                 "bad ipv4 address");
        }
        udp_addr.ipv4.sin_family = AF_INET;
        udp_addr.ipv4.sin_port = htons(endpoint.port);
        memcpy(&udp_addr.ipv4.sin_addr, net_addr.ipv4().addr.data(),
               sizeof(udp_addr.ipv4.sin_addr));
        return udp_addr;
      case fuchsia::net::IpAddress::Tag::kIpv6:
        if (!net_addr.is_ipv6()) {
          return overnet::Status(overnet::StatusCode::INVALID_ARGUMENT,
                                 "bad ipv6 address");
        }
        udp_addr.ipv6.sin6_family = AF_INET6;
        udp_addr.ipv6.sin6_port = htons(endpoint.port);
        memcpy(&udp_addr.ipv6.sin6_addr, net_addr.ipv6().addr.data(),
               sizeof(udp_addr.ipv6.sin6_addr));
        return udp_addr;
    }
    return overnet::Status(overnet::StatusCode::INVALID_ARGUMENT,
                           "bad address family");
  }

  // fuchsia::net::mdns::ServiceSubscriber implementation.
  void OnInstanceDiscovered(fuchsia::net::mdns::ServiceInstance instance,
                            OnInstanceDiscoveredCallback callback) {
    HandleDiscoverOrUpdate(instance, false);
    callback();
  }

  void OnInstanceChanged(fuchsia::net::mdns::ServiceInstance instance,
                         OnInstanceChangedCallback callback) {
    HandleDiscoverOrUpdate(instance, true);
    callback();
  }

  void OnInstanceLost(std::string service, std::string instance,
                      OnInstanceLostCallback callback) {
    callback();
  }

  UdpNub* const nub_;
  fidl::Binding<fuchsia::net::mdns::ServiceSubscriber> subscriber_binding_;
};

MdnsIntroducer::MdnsIntroducer(OvernetApp* app, UdpNub* udp_nub)
    : app_(app), udp_nub_(udp_nub) {}

overnet::Status MdnsIntroducer::Start() {
  auto impl = fbl::MakeRefCounted<Impl>(udp_nub_);
  impl_ = std::move(impl);
  impl_->Begin(app_->component_context());
  return overnet::Status::Ok();
}

MdnsIntroducer::~MdnsIntroducer() {}

class MdnsAdvertisement::Impl
    : public fuchsia::net::mdns::PublicationResponder {
 public:
  Impl(sys::ComponentContext* component_context, UdpNub* nub)
      : publisher_(ConnectToPublisher(component_context, "Advertisement")),
        node_id_(nub->node_id()),
        binding_(this),
        port_(nub->port()) {
    std::cerr << "Requesting mDNS advertisement for " << node_id_ << " on port "
              << nub->port() << "\n";
    publisher_->PublishServiceInstance(
        kServiceName, node_id_.ToString(), true, binding_.NewBinding(),
        [node_id = node_id_, port = port_](
            fuchsia::net::mdns::Publisher_PublishServiceInstance_Result
                result) {
          if (result.is_err()) {
            std::cout << "Advertising " << node_id << " on port " << port
                      << " via mdns gets: " << result.err() << "\n";
          } else {
            std::cout << "Advertising " << node_id << " on port " << port
                      << " via mdns succeeded\n";
          }
        });
  }
  ~Impl() = default;

 private:
  // fuchsia::net::mdns::PublicationResponder implementation.
  void OnPublication(bool query, fidl::StringPtr subtype,
                     OnPublicationCallback callback) {
    callback(subtype->empty()
                 ? std::make_unique<fuchsia::net::mdns::Publication>(
                       fuchsia::net::mdns::Publication{.port = port_})
                 : nullptr);
  }

  const fuchsia::net::mdns::PublisherPtr publisher_;
  const overnet::NodeId node_id_;
  fidl::Binding<fuchsia::net::mdns::PublicationResponder> binding_;
  const uint16_t port_;
};

MdnsAdvertisement::MdnsAdvertisement(OvernetApp* app, UdpNub* udp_nub)
    : app_(app), udp_nub_(udp_nub) {}

overnet::Status MdnsAdvertisement::Start() {
  impl_.reset(new Impl(app_->component_context(), udp_nub_));
  return overnet::Status::Ok();
}

MdnsAdvertisement::~MdnsAdvertisement() {}

}  // namespace overnetstack
