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

#ifndef MINIOS_NETWORK_MANAGER_H_
#define MINIOS_NETWORK_MANAGER_H_

#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <base/memory/weak_ptr.h>
#include <gtest/gtest_prod.h>  // for FRIEND_TEST

#include "minios/network_manager_interface.h"
#include "minios/shill_proxy_interface.h"

namespace minios {

class NetworkManager : public NetworkManagerInterface {
 public:
  // The delay in milliseconds before retrying connection to network.
  static const int kConnectionRetryMsDelay = 500;
  // The delay in milliseconds before checking connection state.
  static const int kCheckConnectionRetryMsDelay = 1000;

  explicit NetworkManager(std::unique_ptr<ShillProxyInterface> shill_proxy);
  virtual ~NetworkManager() = default;

  NetworkManager(const NetworkManager&) = delete;
  NetworkManager& operator=(const NetworkManager&) = delete;

  // NetworkManagerInterface overrides.
  void Connect(const std::string& ssid, const std::string& passphrase) override;
  void GetNetworks() override;

 private:
  friend class NetworkManagerTest;
  FRIEND_TEST(NetworkManagerTest, Connect);
  FRIEND_TEST(NetworkManagerTest, Connect_RequestScanSuccess_NoPassphrase);
  FRIEND_TEST(NetworkManagerTest, Connect_RequestScanSuccess_Passphrase);
  FRIEND_TEST(NetworkManagerTest, Connect_GetServiceSuccess_GoodStrength);
  FRIEND_TEST(NetworkManagerTest, Connect_GetServiceSuccess_BadStrength);
  FRIEND_TEST(NetworkManagerTest, Connect_GetServiceSuccess_MissingStrength);
  FRIEND_TEST(NetworkManagerTest,
              Connect_ConnectToNetworkError_InProgressRetriesConnection);
  FRIEND_TEST(NetworkManagerTest,
              Connect_ConnectToNetworkError_AlreadyConnected);
  FRIEND_TEST(NetworkManagerTest,
              Connect_ConnectToNetworkError_OtherErrorResponsesFromShill);
  FRIEND_TEST(NetworkManagerTest,
              Connect_GetServiceCheckConnectionSuccess_FailureState);
  FRIEND_TEST(NetworkManagerTest,
              Connect_GetServiceCheckConnectionSuccess_OnlineState);
  FRIEND_TEST(NetworkManagerTest,
              Connect_GetServiceCheckConnectionSuccess_MissingState);
  FRIEND_TEST(NetworkManagerTest,
              Connect_GetServiceCheckConnectionSuccess_IntermediateState);
  FRIEND_TEST(NetworkManagerTest, GetNetworks);
  FRIEND_TEST(NetworkManagerTest, GetGlobalPropertiesSuccess_MultipleServices);
  FRIEND_TEST(NetworkManagerTest, GetGlobalPropertiesSuccess_EmptyServices);
  FRIEND_TEST(NetworkManagerTest,
              IterateOverServicePropertiesSuccess_EmptyServices);
  FRIEND_TEST(NetworkManagerTest,
              IterateOverServicePropertiesSuccess_OneService);
  FRIEND_TEST(NetworkManagerTest,
              IterateOverServicePropertiesSuccess_MoreServicesToIterate);
  FRIEND_TEST(NetworkManagerTest,
              IterateOverServicePropertiesError_MoreServicesToIterate);
  FRIEND_TEST(NetworkManagerTest,
              IterateOverServicePropertiesError_AlwaysReturnOnEnd);

  typedef struct {
    std::string passphrase;
    // The service path for the SSID.
    dbus::ObjectPath service_path;
  } ConnectField;
  // Mapping from SSID to `ConnectField`.
  using ConnectMapType = std::unordered_map<std::string, ConnectField>;
  using ConnectMapIter = ConnectMapType::iterator;

  typedef struct {
    // The scanned list of services to go over.
    std::vector<dbus::ObjectPath> service_paths;
    // The network names that is built up.
    std::vector<NetworkProperties> networks;
  } GetNetworksField;
  using GetNetworksListType = std::vector<GetNetworksField>;
  using GetNetworksListIter = GetNetworksListType::iterator;

  // Member function types for `*RequestScan()`s.
  using ConnectRequestScanSuccessType =
      void (NetworkManager::*)(ConnectMapIter);
  using ConnectRequestScanErrorType = void (NetworkManager::*)(ConnectMapIter,
                                                               brillo::Error*);
  using GetNetworksRequestScanSuccessType =
      void (NetworkManager::*)(GetNetworksListIter);
  using GetNetworksRequestScanErrorType =
      void (NetworkManager::*)(GetNetworksListIter, brillo::Error*);

  // `Connect()` sequence.
  // `ManagerRequestScan()` callbacks.
  void RequestScanSuccess(ConnectMapIter iter);
  void RequestScanError(ConnectMapIter iter, brillo::Error* error);
  // `ManagerFindMatchingService()` callbacks.
  void FindServiceSuccess(ConnectMapIter iter,
                          const dbus::ObjectPath& service_path);
  void FindServiceError(ConnectMapIter iter, brillo::Error* error);
  // `ServiceGetProperties()` callbacks.
  void GetServiceSuccess(ConnectMapIter iter,
                         const brillo::VariantDictionary& dict);
  void GetServiceError(ConnectMapIter iter, brillo::Error* error);
  // `ServiceSetProperties()` callbacks.
  void ConfigureNetworkSuccess(ConnectMapIter iter);
  void ConfigureNetworkError(ConnectMapIter iter, brillo::Error* error);
  void ServiceConnect(ConnectMapIter iter);
  // `ServiceConnect()` callbacks.
  void ConnectToNetworkSuccess(ConnectMapIter iter);
  void ConnectToNetworkError(ConnectMapIter iter, brillo::Error* error);
  // `ServiceGetProperties()` callbacks on connection sanity check.
  void GetServiceCheckConnectionSuccess(ConnectMapIter iter,
                                        const brillo::VariantDictionary& dict);
  void GetServiceCheckConnectionError(ConnectMapIter iter,
                                      brillo::Error* error);
  // Response helpers for `ConnectMapIter`.
  void Return(ConnectMapIter iter, brillo::Error* error = nullptr);

  // `GetNetworks()` sequence.
  // `ManagerRequestScan()` callbacks.
  void RequestScanSuccess(GetNetworksListIter iter);
  void RequestScanError(GetNetworksListIter iter, brillo::Error* error);
  // `ManagerGetProperties()` callbacks.
  void GetGlobalPropertiesSuccess(GetNetworksListIter iter,
                                  const brillo::VariantDictionary& dict);
  void GetGlobalPropertiesError(GetNetworksListIter iter, brillo::Error* error);
  // `ServiceGetProperties()` callbacks.
  void IterateOverServicePropertiesSuccess(
      GetNetworksListIter iter, const brillo::VariantDictionary& dict);
  void IterateOverServicePropertiesError(GetNetworksListIter iter,
                                         brillo::Error* error);
  // Response helpers for `GetNetworksListIter`.
  void Return(GetNetworksListIter iter, brillo::Error* error = nullptr);

  ConnectMapType connect_map_;
  GetNetworksListType get_networks_list_;

  std::unique_ptr<ShillProxyInterface> shill_proxy_;

  base::WeakPtrFactory<NetworkManager> weak_ptr_factory_;
};

}  // namespace minios

#endif  // MINIOS_NETWORK_MANAGER_H__
