// Copyright 2020 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 "stack_impl.h"

#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include <zircon/types.h>

#include <string>

// clang-format off
#pragma GCC diagnostic push
#include <Weave/DeviceLayer/PlatformManager.h>
#include <Weave/DeviceLayer/ConfigurationManager.h>
#pragma GCC diagnostic pop
// clang-format on

#include "stack_utils.h"

namespace weavestack {
namespace {

using fuchsia::weave::ErrorCode;
using fuchsia::weave::HostPort;
using fuchsia::weave::PairingState;
using fuchsia::weave::PairingStateWatcher;
using fuchsia::weave::QrCode;
using fuchsia::weave::ResetConfigFlags;
using fuchsia::weave::Stack_GetQrCode_Response;
using fuchsia::weave::Stack_GetQrCode_Result;
using fuchsia::weave::Stack_ResetConfig_Response;
using fuchsia::weave::Stack_ResetConfig_Result;
using fuchsia::weave::SvcDirectoryWatcher;

using nl::Weave::DeviceLayer::ConfigurationMgr;
using nl::Weave::DeviceLayer::PlatformMgrImpl;
using nl::Weave::DeviceLayer::WeaveDeviceEvent;
using nl::Weave::DeviceLayer::DeviceEventType::kAccountPairingChange;
using nl::Weave::DeviceLayer::DeviceEventType::kFabricMembershipChange;
using nl::Weave::DeviceLayer::DeviceEventType::kServiceProvisioningChange;
using nl::Weave::DeviceLayer::DeviceEventType::kServiceTunnelStateChange;
using nl::Weave::Profiles::DeviceControl::DeviceControlDelegate;

// Size of the buffer for retrieving the QR code.
constexpr size_t kQrCodeBufSize = fuchsia::weave::MAX_QR_CODE_SIZE + 1;
// Size of the buffer for retrieving hostnames.
constexpr size_t kHostnameBufferSize = fuchsia::net::MAX_HOSTNAME_SIZE + 1;
}  // namespace

// Watcher class declarations --------------------------------------------------

class StackImpl::PairingStateWatcherImpl : public PairingStateWatcher {
 public:
  explicit PairingStateWatcherImpl(StackImpl* stack);

  /// Returns the state of pairing
  ///
  /// First call returns the current pairing state or blocks until the pairing
  /// state is available. Subsequent calls will block until the pairing state
  /// changes.
  void WatchPairingState(WatchPairingStateCallback callback) override;

  /// Notify that pairing state has changed.
  zx_status_t Notify();

 private:
  /// Perform the callback if there is an active watcher.
  zx_status_t DoCallback();

  // Prevent copy construction.
  PairingStateWatcherImpl(const PairingStateWatcherImpl&) = delete;
  // Prevent copy assignment.
  PairingStateWatcherImpl& operator=(const PairingStateWatcherImpl&) = delete;

  StackImpl* stack_;
  bool dirty_ = false;
  bool first_call_ = true;
  WatchPairingStateCallback pairing_state_callback_;
};

class StackImpl::SvcDirectoryWatcherImpl : public SvcDirectoryWatcher {
 public:
  explicit SvcDirectoryWatcherImpl(StackImpl* stack, uint64_t endpoint_id);

  /// Returns a vector of HostPorts for the watched endpoint ID.
  ///
  /// First call returns the current list of HostPorts or blocks until the list
  /// is available from the service. Subsequent calls will block until a new
  /// ServiceDirectory lookup is made and will return the list associated with
  /// the watched endpoint ID, which may or may not be the same as prior values.
  void WatchServiceDirectory(WatchServiceDirectoryCallback callback) override;

  /// Notify that watched service directory has changed.
  zx_status_t Notify();

 private:
  /// Perform the callback if there is an active watcher.
  zx_status_t DoCallback();

  // Prevent copy construction.
  SvcDirectoryWatcherImpl(const SvcDirectoryWatcherImpl&) = delete;
  // Prevent copy assignment.
  SvcDirectoryWatcherImpl& operator=(const SvcDirectoryWatcherImpl&) = delete;

  StackImpl* stack_;
  bool dirty_ = false;
  bool first_call_ = true;
  uint64_t endpoint_id_;
  WatchServiceDirectoryCallback svc_directory_callback_;
};

// StackImpl definitions -------------------------------------------------------

StackImpl::StackImpl(sys::ComponentContext* context) : context_(context) {}

zx_status_t StackImpl::Init() {
  zx_status_t status = ZX_OK;
  WEAVE_ERROR err = WEAVE_NO_ERROR;

  // Register with the context.
  status = context_->outgoing()->AddPublicService(bindings_.GetHandler(this));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to register StackImpl handler with status ="
                   << zx_status_get_string(status);
    return status;
  }

  // Register event handler with Weave Device Layer.
  err = PlatformMgrImpl().AddEventHandler(TrampolineEvent, reinterpret_cast<intptr_t>(this));
  if (err != WEAVE_NO_ERROR) {
    FX_LOGS(ERROR) << "Failed to register event handler with device layer: " << nl::ErrorStr(err);
    return ZX_ERR_INTERNAL;
  }

  return status;
}

// The destructor must be defined after the full definitions of the watcher
// classes to avoid attempting to use an incomplete definition in the compiler
// generated default destructor.
StackImpl::~StackImpl() = default;

void StackImpl::GetPairingStateWatcher(fidl::InterfaceRequest<PairingStateWatcher> watcher) {
  pairing_state_watchers_.AddBinding(std::make_unique<PairingStateWatcherImpl>(this),
                                     std::move(watcher));
}

void StackImpl::GetSvcDirectoryWatcher(uint64_t endpoint_id,
                                       fidl::InterfaceRequest<SvcDirectoryWatcher> watcher) {
  svc_directory_watchers_.AddBinding(std::make_unique<SvcDirectoryWatcherImpl>(this, endpoint_id),
                                     std::move(watcher));
}

void StackImpl::GetQrCode(GetQrCodeCallback callback) {
  QrCode qr_code;
  Stack_GetQrCode_Response response;
  Stack_GetQrCode_Result result;
  WEAVE_ERROR err;

  // Initialize space for the QR code.
  response.qr_code.data.resize(kQrCodeBufSize, '\0');
  // Copy the QR code into qr_code.data.
  err = ConfigurationMgr().GetQRCodeString(response.qr_code.data.data(),
                                           response.qr_code.data.size());
  if (err != WEAVE_NO_ERROR) {
    FX_LOGS(ERROR) << "Failed to retrieve QR code: " << err;
    result.set_err(ErrorCode::UNSPECIFIED_ERROR);
  } else {
    // Resize to returned length.
    response.qr_code.data.resize(strnlen(response.qr_code.data.data(), kQrCodeBufSize));
    result.set_response(response);
  }

  callback(std::move(result));
}

void StackImpl::ResetConfig(ResetConfigFlags flags, ResetConfigCallback callback) {
  Stack_ResetConfig_Response response;
  Stack_ResetConfig_Result result;

  WEAVE_ERROR err = GetDeviceControl().OnResetConfig(static_cast<uint16_t>(flags));
  if (err != WEAVE_NO_ERROR) {
    result.set_err(ErrorCode::UNSPECIFIED_ERROR);
  } else {
    result.set_response(response);
  }

  callback(std::move(result));
}

void StackImpl::NotifyPairingState() {
  last_pairing_state_ = std::make_unique<PairingState>(CurrentPairingState());
  for (auto& binding : pairing_state_watchers_.bindings()) {
    binding->impl()->Notify();
  }
}

void StackImpl::NotifySvcDirectory() {
  for (auto& binding : svc_directory_watchers_.bindings()) {
    binding->impl()->Notify();
  }
}

void StackImpl::HandleWeaveDeviceEvent(const WeaveDeviceEvent* event) {
  // Handle events.
  switch (event->Type) {
    case kServiceTunnelStateChange:
      if (event->ServiceTunnelStateChange.Result ==
          nl::Weave::DeviceLayer::kConnectivity_Established) {
        // New tunnel established, notify service directory watchers to check
        // for updates to their service directory entries.
        NotifySvcDirectory();
      }
      // TODO(https://fxbug.dev/42130292): Add event for Thread provisioning.
      // TODO(https://fxbug.dev/42130293): Add event for WiFi provisioning.
      __FALLTHROUGH;
    case kFabricMembershipChange:
    case kServiceProvisioningChange:
    case kAccountPairingChange:
      // Pairing/provisioning state has changed, notify watchers.
      NotifyPairingState();
      break;
    default:
      // Ignore all other events.
      break;
  }
}

void StackImpl::TrampolineEvent(const WeaveDeviceEvent* event, intptr_t arg) {
  StackImpl* self = reinterpret_cast<StackImpl*>(arg);
  self->HandleWeaveDeviceEvent(event);
}

DeviceControlDelegate& StackImpl::GetDeviceControl() {
  return PlatformMgrImpl().GetDeviceControl();
}

zx_status_t StackImpl::LookupHostPorts(uint64_t endpoint_id, std::vector<HostPort>* host_ports) {
  WEAVE_ERROR err = WEAVE_NO_ERROR;
  nl::Weave::HostPortList host_port_list;

  // Lookup host endpoints from service directory.
  err = PlatformMgrImpl().GetServiceDirectoryManager().lookup(endpoint_id, &host_port_list);
  if (err == WEAVE_ERROR_INVALID_SERVICE_EP) {
    FX_LOGS(WARNING) << "Invalid service directory endpoint: " << endpoint_id;
    return ZX_ERR_INVALID_ARGS;
  }
  if (err != WEAVE_NO_ERROR) {
    FX_LOGS(ERROR) << "Failed to lookup service directory: " << nl::ErrorStr(err);
    return ZX_ERR_INTERNAL;
  }

  while (!host_port_list.IsEmpty()) {
    HostPort host_port;
    char hostname_buf[kHostnameBufferSize] = {};
    uint16_t port = 0;

    // Extract HostPort info from host_port_list.
    err = host_port_list.Pop(hostname_buf, kHostnameBufferSize, port);
    if (err != WEAVE_NO_ERROR) {
      FX_LOGS(ERROR) << "Failed to extract host/port in HostPortList: " << nl::ErrorStr(err);
      return ZX_ERR_INTERNAL;
    }

    // Convert to FIDL HostPort.
    host_port.host = HostFromHostname(hostname_buf);
    host_port.port = port;

    // Push onto returned HostPort vector.
    host_ports->emplace_back(std::move(host_port));
  }

  return ZX_OK;
}

// Watcher class definitions ---------------------------------------------------

StackImpl::PairingStateWatcherImpl::PairingStateWatcherImpl(StackImpl* stack) : stack_(stack) {}

void StackImpl::PairingStateWatcherImpl::WatchPairingState(WatchPairingStateCallback callback) {
  // Check to make sure there isn't a waiting callback already.
  if (pairing_state_callback_) {
    stack_->pairing_state_watchers_.CloseBinding(this, ZX_ERR_BAD_STATE);
    return;
  }

  // Save callback for sending result (potentially async).
  pairing_state_callback_ = std::move(callback);
  // Callback to caller if data is ready.
  DoCallback();
}

zx_status_t StackImpl::PairingStateWatcherImpl::Notify() {
  // Mark dirty.
  dirty_ = true;
  // Perform callback if there is a waiting client.
  return DoCallback();
}

zx_status_t StackImpl::PairingStateWatcherImpl::DoCallback() {
  zx_status_t status = ZX_OK;
  PairingState pairing_state;

  // Only perform callback if ready.
  if (!pairing_state_callback_ || !(dirty_ || first_call_)) {
    return ZX_OK;
  }

  // Allocate pairing state if not present.
  if (!stack_->last_pairing_state_) {
    stack_->last_pairing_state_ = std::make_unique<PairingState>(CurrentPairingState());
  }

  // Reset for next callback.
  WatchPairingStateCallback callback = std::move(pairing_state_callback_);
  dirty_ = false;
  first_call_ = false;

  // Copy the pairing state into return value.
  status = stack_->last_pairing_state_->Clone(&pairing_state);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to clone pairing state: " << zx_status_get_string(status)
                   << ", cannot send callback!";
    stack_->pairing_state_watchers_.CloseBinding(this, status);
    return status;
  }

  // Send updated pairing state to caller.
  callback(std::move(pairing_state));
  return ZX_OK;
}

StackImpl::SvcDirectoryWatcherImpl::SvcDirectoryWatcherImpl(StackImpl* stack, uint64_t endpoint_id)
    : stack_(stack), endpoint_id_(endpoint_id) {}

void StackImpl::SvcDirectoryWatcherImpl::WatchServiceDirectory(
    WatchServiceDirectoryCallback callback) {
  // Check to make sure there isn't a waiting callback already.
  if (svc_directory_callback_) {
    stack_->svc_directory_watchers_.CloseBinding(this, ZX_ERR_BAD_STATE);
    return;
  }

  // Save callback for sending result (potentially async).
  svc_directory_callback_ = std::move(callback);
  // Attempt to reply if first call or dirty data.
  DoCallback();
}

zx_status_t StackImpl::SvcDirectoryWatcherImpl::Notify() {
  // Mark dirty.
  dirty_ = true;
  // Perform callback if there is a waiting client.
  return DoCallback();
}

zx_status_t StackImpl::SvcDirectoryWatcherImpl::DoCallback() {
  std::vector<HostPort> host_ports;

  if (!svc_directory_callback_ || !(dirty_ || first_call_)) {
    return ZX_OK;
  }

  // Reset for next callback.
  WatchServiceDirectoryCallback callback = std::move(svc_directory_callback_);
  dirty_ = false;
  first_call_ = false;

  // Lookup the (potentially new) HostPorts.
  zx_status_t status = stack_->LookupHostPorts(endpoint_id_, &host_ports);
  if (status != ZX_OK) {
    stack_->svc_directory_watchers_.CloseBinding(this, status);
    return status;
  }

  // Call callback.
  first_call_ = false;
  callback(std::move(host_ports));

  return ZX_OK;
}

}  // namespace weavestack
