// 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/internal/BLEManager.h>
#include <Weave/DeviceLayer/internal/DeviceNetworkInfo.h>
#include <Weave/DeviceLayer/internal/ServiceTunnelAgent.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/net/interfaces/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>

namespace nl {
namespace Weave {
namespace DeviceLayer {

namespace {

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

using Internal::ServiceTunnelAgent;

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

  switch (reason) {
    case WeaveTunnelConnectionMgr::kStatus_TunDown:
      new_tunnel_state = false;
      FX_LOGS(INFO) << "Service tunnel down.";
      break;
    case WeaveTunnelConnectionMgr::kStatus_TunPrimaryConnError:
      new_tunnel_state = false;
      FX_LOGS(ERROR) << "Service tunnel connection error: " << ::nl::ErrorStr(err);
      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;
      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 {
    StopServiceTunnel(WEAVE_NO_ERROR);
  }
}

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);
    }
  } else if (event.is_removed()) {
    routable_v4_interfaces.erase(event.removed());
    routable_v6_interfaces.erase(event.removed());
  }

  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));
}

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