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

// clang-format off
#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/DeviceLayer/ConnectivityManager.h>
#include <Weave/DeviceLayer/ThreadStackManager.h>
#include <Weave/DeviceLayer/internal/BLEManager.h>
#include <Weave/DeviceLayer/internal/DeviceNetworkInfo.h>
#include <Weave/DeviceLayer/internal/ServiceTunnelAgent.h>
#include <Weave/DeviceLayer/ThreadStackManager.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Warm/Warm.h>

#if WEAVE_DEVICE_CONFIG_ENABLE_WOBLE
#include <Weave/DeviceLayer/internal/GenericConnectivityManagerImpl_BLE.ipp>
#endif
// clang-format on
#include "connectivity_manager_delegate_impl.h"

#include <fuchsia/hardware/network/cpp/fidl.h>
#include <fuchsia/net/interfaces/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>

#include "weave_inspector.h"

namespace nl {
namespace Weave {
namespace DeviceLayer {

namespace {

using namespace ::nl::Weave;
using namespace ::nl::Weave::Profiles::WeaveTunnel;

using fuchsia::hardware::network::DeviceClass;
using Internal::ServiceTunnelAgent;
using nl::Weave::WeaveInspector;

using ThreadMode = ConnectivityManager::ThreadMode;

constexpr ThreadMode kThreadMode_NotSupported = ConnectivityManager::kThreadMode_NotSupported;
constexpr ThreadMode kThreadMode_Disabled = ConnectivityManager::kThreadMode_Disabled;
constexpr ThreadMode kThreadMode_Enabled = ConnectivityManager::kThreadMode_Enabled;

// Returns a pointer to the ServiceTunnelAgent instance.
WeaveTunnelAgent* SrvTunnelAgent() { return &ServiceTunnelAgent; }

}  // unnamed namespace

bool ConnectivityManagerDelegateImpl::IsServiceTunnelConnected(void) {
  WeaveTunnelAgent::AgentState tunnel_state = SrvTunnelAgent()->GetWeaveTunnelAgentState();
  return (tunnel_state == WeaveTunnelAgent::kState_PrimaryTunModeEstablished ||
          tunnel_state == WeaveTunnelAgent::kState_PrimaryAndBkupTunModeEstablished ||
          tunnel_state == WeaveTunnelAgent::kState_BkupOnlyTunModeEstablished);
}

bool ConnectivityManagerDelegateImpl::IsServiceTunnelRestricted(void) {
  return SrvTunnelAgent()->IsTunnelRoutingRestricted();
}

void ConnectivityManagerDelegateImpl::HandleServiceTunnelNotification(
    WeaveTunnelConnectionMgr::TunnelConnNotifyReasons reason, WEAVE_ERROR err, void* app_ctx) {
  ConnectivityManagerDelegateImpl* delegate = (ConnectivityManagerDelegateImpl*)app_ctx;
  bool new_tunnel_state = false;
  bool prev_tunnel_state = GetFlag(delegate->flags_, kFlag_ServiceTunnelUp);
  bool is_restricted = false;
  auto& inspector = WeaveInspector::GetWeaveInspector();
  switch (reason) {
    case WeaveTunnelConnectionMgr::kStatus_TunDown:
      new_tunnel_state = false;
      FX_LOGS(INFO) << "Service tunnel down.";
      inspector.NotifyTunnelStateChange(WeaveInspector::kTunnelState_NoTunnel,
                                        WeaveInspector::kTunnelType_None, is_restricted);
      break;
    case WeaveTunnelConnectionMgr::kStatus_TunPrimaryConnError:
      new_tunnel_state = false;
      FX_LOGS(ERROR) << "Service tunnel connection error: " << ::nl::ErrorStr(err);
      inspector.NotifyTunnelStateChange(WeaveInspector::kTunnelState_NoTunnel,
                                        WeaveInspector::kTunnelType_None, is_restricted);
      break;
    case WeaveTunnelConnectionMgr::kStatus_TunPrimaryUp:
      new_tunnel_state = true;
      is_restricted = (err == WEAVE_ERROR_TUNNEL_ROUTING_RESTRICTED);
      FX_LOGS(INFO) << "Service tunnel established, restricted: " << is_restricted;
      inspector.NotifyTunnelStateChange(WeaveInspector::kTunnelState_PrimaryTunMode,
                                        WeaveInspector::kTunnelType_Primary, is_restricted);
      break;
    default:
      break;
  }

  // Ignore event if the tunnel state has not changed.
  if (new_tunnel_state == prev_tunnel_state) {
    return;
  }

  // Update the cached copy of the state.
  SetFlag(delegate->flags_, kFlag_ServiceTunnelUp, new_tunnel_state);

  // Alert other components of the change to the tunnel state.
  WeaveDeviceEvent tunnel_event;
  tunnel_event.Type = DeviceEventType::kServiceTunnelStateChange;
  tunnel_event.ServiceTunnelStateChange.Result =
      GetConnectivityChange(prev_tunnel_state, new_tunnel_state);
  tunnel_event.ServiceTunnelStateChange.IsRestricted = is_restricted;
  PlatformMgrImpl().PostEvent(&tunnel_event);

  // If the new tunnel state represents a logical change in connectivity to the
  // service, as it relates to the application, post a ServiceConnectivityChange
  // event.
  // Establishment of a restricted tunnel to service does not constitute a
  // logical change in connectivity from an application's perspective, so ignore
  // the event in that case.
  if (new_tunnel_state && is_restricted) {
    return;
  }
  WeaveDeviceEvent service_event;
  service_event.Type = DeviceEventType::kServiceConnectivityChange;
  service_event.ServiceConnectivityChange.ViaTunnel.Result =
      (new_tunnel_state) ? kConnectivity_Established : kConnectivity_Lost;
  service_event.ServiceConnectivityChange.ViaThread.Result = kConnectivity_NoChange;
  service_event.ServiceConnectivityChange.Overall.Result =
      ConnectivityMgr().HaveServiceConnectivityViaThread()
          ? kConnectivity_NoChange
          : service_event.ServiceConnectivityChange.ViaTunnel.Result;
  PlatformMgrImpl().PostEvent(&service_event);
}

void ConnectivityManagerDelegateImpl::StartServiceTunnel() {
  if (GetFlag(flags_, kFlag_ServiceTunnelStarted)) {
    return;
  }
  // Update the tunnel started state.
  FX_LOGS(INFO) << "Starting service tunnel";
  WEAVE_ERROR err = SrvTunnelAgent()->StartServiceTunnel();
  if (err != WEAVE_NO_ERROR) {
    FX_LOGS(ERROR) << "StartServiceTunnel() failed: " << nl::ErrorStr(err);
    return;
  }
  SetFlag(flags_, kFlag_ServiceTunnelStarted, true);
}

void ConnectivityManagerDelegateImpl::StopServiceTunnel(WEAVE_ERROR err) {
  if (GetFlag(flags_, kFlag_ServiceTunnelStarted) == false) {
    return;
  }
  // Update the tunnel started state.
  FX_LOGS(INFO) << "Stopping service tunnel";
  SrvTunnelAgent()->StopServiceTunnel(err);
  SetFlag(flags_, kFlag_ServiceTunnelStarted, false);
}

WEAVE_ERROR ConnectivityManagerDelegateImpl::Init() {
  WEAVE_ERROR err = WEAVE_NO_ERROR;

  // Reset internal flags to clear any pre-existing state.
  service_tunnel_mode_ = ConnectivityManager::kServiceTunnelMode_Enabled;
  flags_ = 0;

  // Initialize the Weave Addressing and Routing Module.
  err = Warm::Init(FabricState);
  if (err != WEAVE_NO_ERROR) {
    FX_LOGS(ERROR) << "Warm Init failed : " << nl::ErrorStr(err);
    return err;
  }

  // Initialize tunnel agent.
  err = InitServiceTunnelAgent();
  if (err != WEAVE_NO_ERROR) {
    FX_LOGS(ERROR) << "InitServiceTunnelAgent failed : " << nl::ErrorStr(err);
    return err;
  }

  // Bind tunnel notification handler.
  SrvTunnelAgent()->OnServiceTunStatusNotify = HandleServiceTunnelNotification;

  // Watch for interface updates.
  err = PlatformMgrImpl().GetComponentContextForProcess()->svc()->Connect(state_.NewRequest());
  if (err != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to register state watcher." << zx_status_get_string(err);
    return err;
  }
  state_.set_error_handler([](zx_status_t status) {
    // Treat connection loss to netstack as fatal and inform applications that
    // they should attempt a graceful shutdown / restart.
    FX_LOGS(ERROR) << "Disconnected from netstack: " << zx_status_get_string(status);
    const WeaveDeviceEvent shutdown_request = {
        .Type = WeaveDevicePlatformEventType::kShutdownRequest,
    };
    PlatformMgrImpl().PostEvent(&shutdown_request);
  });

  fuchsia::net::interfaces::WatcherOptions options;
  state_->GetWatcher(std::move(options), watcher_.NewRequest());
  if (!watcher_.is_bound()) {
    FX_LOGS(ERROR) << "Failed to bind watcher.";
    return WEAVE_ERROR_INCORRECT_STATE;
  }
  watcher_->Watch(fit::bind_member(this, &ConnectivityManagerDelegateImpl::OnInterfaceEvent));
  return err;
}

WEAVE_ERROR ConnectivityManagerDelegateImpl::InitServiceTunnelAgent() {
  return Internal::InitServiceTunnelAgent(this);
}

void ConnectivityManagerDelegateImpl::DriveServiceTunnelState() {
  bool should_start_service_tunnel =
      (service_tunnel_mode_ == ConnectivityManager::kServiceTunnelMode_Enabled) &&
      GetFlag(flags_, kFlag_HaveIPv4InternetConnectivity | kFlag_HaveIPv6InternetConnectivity) &&
      ConfigurationMgr().IsMemberOfFabric() && ConfigurationMgr().IsServiceProvisioned();

  if (should_start_service_tunnel == GetFlag(flags_, kFlag_ServiceTunnelStarted)) {
    return;
  }

  if (should_start_service_tunnel) {
    StartServiceTunnel();
  } else {
    // Forcefully abort the tunnel when the device loses connectivity as this
    // ensures the proper release of resources like timers. This stops tunnel
    // retry mechanism when there is no connectivity. The tunnel will be
    // restarted explicitly, when the connectivity is restored.
    StopServiceTunnel(WEAVE_ERROR_TUNNEL_FORCE_ABORT);
  }
}

void ConnectivityManagerDelegateImpl::OnPlatformEvent(const WeaveDeviceEvent* event) {
  if (event == NULL) {
    return;
  }
  switch (event->Type) {
    case DeviceEventType::kFabricMembershipChange:
    case DeviceEventType::kServiceProvisioningChange:
      DriveServiceTunnelState();
      break;
    case DeviceEventType::kAccountPairingChange:
      // When account pairing successfully completes, if the tunnel to the
      // service is subject to routing restrictions (imposed because at the time
      // the tunnel was established the device was not paired to an account)
      // then force the tunnel to close.  This will result in the tunnel being
      // re-established, which should lift the service-side restrictions.
      if (event->AccountPairingChange.IsPairedToAccount &&
          GetFlag(flags_, kFlag_ServiceTunnelStarted) && IsServiceTunnelRestricted()) {
        FX_LOGS(INFO) << "Restarting service tunnel to lift routing restrictions";
        StopServiceTunnel(WEAVE_ERROR_TUNNEL_FORCE_ABORT);
        StartServiceTunnel();
      }
      break;
    default:
      break;
  }
}

WEAVE_ERROR ConnectivityManagerDelegateImpl::RefreshEndpoints() {
  return MessageLayer.RefreshEndpoints();
}

void ConnectivityManagerDelegateImpl::OnInterfaceEvent(fuchsia::net::interfaces::Event event) {
  fuchsia::net::interfaces::Properties properties;
  bool properties_event = true;

  if (event.is_existing()) {
    properties = std::move(event.existing());
  } else if (event.is_added()) {
    properties = std::move(event.added());
  } else if (event.is_changed()) {
    properties = std::move(event.changed());
  } else {
    properties_event = false;
  }

  // If a properties event, record the ID of the interface into the
  // corresponding interface list. If removed or the route was lost,
  // remove it from the interface list.
  if (properties_event) {
    if (properties.has_has_default_ipv4_route()) {
      if (properties.has_default_ipv4_route()) {
        routable_v4_interfaces.insert(properties.id());
      } else {
        routable_v4_interfaces.erase(properties.id());
      }
    }
    if (properties.has_has_default_ipv6_route()) {
      if (properties.has_default_ipv6_route()) {
        routable_v6_interfaces.insert(properties.id());
      } else {
        routable_v6_interfaces.erase(properties.id());
      }
    }
    if (event.is_changed() && properties.has_online()) {
      PlatformMgr().ScheduleWork(
          [](intptr_t context) {
            ConnectivityManagerDelegateImpl* delegate = (ConnectivityManagerDelegateImpl*)context;
            WEAVE_ERROR err = delegate->RefreshEndpoints();
            if (err != WEAVE_NO_ERROR) {
              FX_LOGS(ERROR) << "MessageLayer.RefreshEndpoints() failed: " << nl::ErrorStr(err);
            }
          },
          (intptr_t)this);
    }

    // TODO(73097): Instead of attempting to "detect" the right interface (and assuming the first
    // interface that matches is correct), allow the wlan and thread interfaces to be specified via
    // config.

    if (wlan_interface_id_ == 0 && properties.has_device_class() &&
        properties.device_class().is_device() &&
        properties.device_class().device() == DeviceClass::WLAN) {
      wlan_interface_id_ = properties.id();
      wlan_interface_name_ = properties.name();
      FX_LOGS(INFO) << "Identifying interface \"" << properties.name()
                    << "\" as the WLAN interface.";
      PlatformMgr().ScheduleWork(
          [](intptr_t) { Warm::WiFiInterfaceStateChange(Warm::kInterfaceStateUp); }, 0);
    }

    if (thread_interface_id_ == 0 && properties.has_name() &&
        properties.name() == ThreadStackMgrImpl().GetInterfaceName()) {
      thread_interface_id_ = properties.id();
      FX_LOGS(INFO) << "Identifying interface \"" << properties.name()
                    << "\" as the Thread interface.";
      PlatformMgr().ScheduleWork(
          [](intptr_t) { Warm::ThreadInterfaceStateChange(Warm::kInterfaceStateUp); }, 0);
    }
  } else if (event.is_removed()) {
    routable_v4_interfaces.erase(event.removed());
    routable_v6_interfaces.erase(event.removed());

    if (event.removed() == wlan_interface_id_) {
      FX_LOGS(INFO) << "Wlan iface removed, informing WARM of WLAN down.";
      PlatformMgr().ScheduleWork(
          [](intptr_t context) {
            auto self = reinterpret_cast<ConnectivityManagerDelegateImpl*>(context);
            Warm::WiFiInterfaceStateChange(Warm::kInterfaceStateDown);
            self->wlan_interface_id_ = 0;
            self->wlan_interface_name_ = std::nullopt;
          },
          reinterpret_cast<intptr_t>(this));
    } else if (event.removed() == thread_interface_id_) {
      FX_LOGS(INFO) << "Thread iface removed, informing WARM of Thread down.";
      PlatformMgr().ScheduleWork(
          [](intptr_t context) {
            auto self = reinterpret_cast<ConnectivityManagerDelegateImpl*>(context);
            Warm::ThreadInterfaceStateChange(Warm::kInterfaceStateDown);
            self->thread_interface_id_ = 0;
          },
          reinterpret_cast<intptr_t>(this));
    }
  }

  PlatformMgr().ScheduleWork(
      [](intptr_t context) {
        ConnectivityManagerDelegateImpl* delegate = (ConnectivityManagerDelegateImpl*)context;
        SetFlag(delegate->flags_, kFlag_HaveIPv4InternetConnectivity,
                !delegate->routable_v4_interfaces.empty());
        SetFlag(delegate->flags_, kFlag_HaveIPv6InternetConnectivity,
                !delegate->routable_v6_interfaces.empty());
        delegate->DriveServiceTunnelState();
      },
      (intptr_t)this);

  watcher_->Watch(fit::bind_member(this, &ConnectivityManagerDelegateImpl::OnInterfaceEvent));
}

std::optional<std::string> ConnectivityManagerDelegateImpl::GetWiFiInterfaceName() {
  return wlan_interface_name_;
}

ThreadMode ConnectivityManagerDelegateImpl::GetThreadMode() {
  if (!ThreadStackMgrImpl().IsThreadSupported()) {
    return kThreadMode_NotSupported;
  }

  return ((ThreadStackMgrImpl()._IsThreadEnabled()) ? (kThreadMode_Enabled) : (kThreadMode_Disabled));
}

}  // namespace DeviceLayer
}  // namespace Weave
}  // namespace nl
