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

#include "shill/cellular/cellular_service_provider.h"

#include <set>
#include <string>
#include <vector>

#include "shill/cellular/cellular_service.h"
#include "shill/logging.h"
#include "shill/manager.h"
#include "shill/store_interface.h"

#include <base/check.h>
#include <base/check_op.h>

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kCellular;
static std::string ObjectID(const CellularServiceProvider* e) {
  return "(cellular_service_provider)";
}
}  // namespace Logging

namespace {

bool IsValidEid(const std::string& sim_card_id) {
  // eID must be 32 characters in length. Since ICCID is limited to 20
  // characters, this is a strong indicator of a valid eID.
  return sim_card_id.size() == 32;
}

bool GetServiceParametersFromArgs(const KeyValueStore& args,
                                  std::string* imsi,
                                  std::string* iccid,
                                  std::string* eid,
                                  Error* error) {
  *iccid =
      args.Lookup<std::string>(CellularService::kStorageIccid, std::string());
  if (iccid->empty()) {
    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
                          "Missing ICCID");
    return false;
  }

  // If SimCardId != ICCID, it matches the eID. TODO(b/182943364): Store eID.
  std::string sim_card_id = args.Lookup<std::string>(
      CellularService::kStorageSimCardId, std::string());
  if (sim_card_id != *iccid) {
    if (IsValidEid(sim_card_id)) {
      *eid = sim_card_id;
    } else {
      LOG(ERROR) << "Unexpected SIM Card Id: " << sim_card_id;
      *eid = "";
    }
  } else {
    *eid = "";
  }

  // IMSI may be empty.
  *imsi =
      args.Lookup<std::string>(CellularService::kStorageImsi, std::string());

  return true;
}

bool GetServiceParametersFromStorage(const StoreInterface* storage,
                                     const std::string& entry_name,
                                     std::string* imsi,
                                     std::string* iccid,
                                     std::string* eid,
                                     Error* error) {
  if (!storage->GetString(entry_name, CellularService::kStorageIccid, iccid) ||
      iccid->empty()) {
    Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
                          "Missing or empty ICCID");
    return false;
  }

  // If SimCardId != ICCID, it matches the eID. TODO(b/182943364): Store eID.
  std::string sim_card_id;
  if (storage->GetString(entry_name, CellularService::kStorageSimCardId,
                         &sim_card_id) &&
      sim_card_id != *iccid) {
    if (IsValidEid(sim_card_id)) {
      *eid = sim_card_id;
    } else {
      LOG(ERROR) << "Unexpected SIM Card Id: " << sim_card_id;
      *eid = "";
    }
  } else {
    *eid = "";
  }

  // IMSI may be empty.
  storage->GetString(entry_name, CellularService::kStorageImsi, imsi);

  return true;
}

}  // namespace

CellularServiceProvider::CellularServiceProvider(Manager* manager)
    : manager_(manager) {}

CellularServiceProvider::~CellularServiceProvider() = default;

void CellularServiceProvider::CreateServicesFromProfile(
    const ProfileRefPtr& profile) {
  SLOG(this, 2) << __func__ << ": " << profile->GetFriendlyName();
  // A Cellular Device may not exist yet, so we do not load services here.
  // Cellular services associated with a Device are loaded in
  // LoadServicesForDevice when the Device is created. We store |profile| here
  // so that we always use the default profile (see comment in header).
  if (!profile_)
    profile_ = profile;
}

ServiceRefPtr CellularServiceProvider::FindSimilarService(
    const KeyValueStore& args, Error* error) const {
  SLOG(this, 2) << __func__;
  CHECK_EQ(kTypeCellular, args.Lookup<std::string>(kTypeProperty, ""))
      << "Service type must be Cellular!";
  // This is called from Manager::ConfigureServiceForProfile when the Manager
  // dbus api call is made (e.g. from Chrome) for a new service (i.e without
  // an existing GUID). For Cellular, this should never happen.
  Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
                        "Only existing Cellular services can be configured.");
  return nullptr;
}

ServiceRefPtr CellularServiceProvider::GetService(const KeyValueStore& args,
                                                  Error* error) {
  SLOG(this, 2) << __func__;
  // This is called from Manager::GetService or Manager::ConfigureService when
  // the corresponding Manager dbus api call is made (e.g. from Chrome) for a
  // new service (i.e without an existing GUID). For Cellular, this should never
  // happen.
  Error::PopulateAndLog(
      FROM_HERE, error, Error::kNotSupported,
      "GetService must be called with an existing Cellular Service GUID.");
  return nullptr;
}

ServiceRefPtr CellularServiceProvider::CreateTemporaryService(
    const KeyValueStore& args, Error* error) {
  SLOG(this, 2) << __func__;
  std::string imsi, iccid, eid;
  if (GetServiceParametersFromArgs(args, &imsi, &iccid, &eid, error)) {
    return new CellularService(manager_, imsi, iccid, eid);
  }
  return nullptr;
}

ServiceRefPtr CellularServiceProvider::CreateTemporaryServiceFromProfile(
    const ProfileRefPtr& profile, const std::string& entry_name, Error* error) {
  SLOG(this, 2) << __func__ << ": " << profile->GetFriendlyName();
  std::string imsi, iccid, eid;
  if (GetServiceParametersFromStorage(profile->GetConstStorage(), entry_name,
                                      &imsi, &iccid, &eid, error)) {
    return new CellularService(manager_, imsi, iccid, eid);
  }
  return nullptr;
}

void CellularServiceProvider::Start() {
  SLOG(this, 2) << __func__;
}

void CellularServiceProvider::Stop() {
  SLOG(this, 2) << __func__;
  while (!services_.empty())
    RemoveService(services_.back());
}

CellularServiceRefPtr CellularServiceProvider::LoadServicesForDevice(
    Cellular* device) {
  SLOG(this, 2) << __func__ << ": " << device->iccid();

  CellularServiceRefPtr active_service = LoadMatchingServicesFromProfile(
      device->eid(), device->iccid(), device->imsi(), device);

  // When the Cellular SIM changes or Cellular is enabled, assume that the
  // intent is to auto connect to the CellularService (if connectable and
  // AutoConnect are set), even if the service was previously explicitly
  // disconnected.
  active_service->ClearExplicitlyDisconnected();

  return active_service;
}

void CellularServiceProvider::RemoveNonDeviceServices(Cellular* device) {
  SLOG(this, 2) << __func__ << ": " << device->iccid();
  std::vector<CellularServiceRefPtr> services_to_remove;
  for (CellularServiceRefPtr& service : services_) {
    if (!device->HasSimCardId(service->GetSimCardId()))
      services_to_remove.push_back(service);
  }
  for (CellularServiceRefPtr& service : services_to_remove)
    RemoveService(service);
}

CellularServiceRefPtr CellularServiceProvider::LoadMatchingServicesFromProfile(
    const std::string& eid,
    const std::string& iccid,
    const std::string& imsi,
    Cellular* device) {
  DCHECK(device);
  // Find Cellular profile entries matching the sim card identifier.
  DCHECK(profile_);
  StoreInterface* storage = profile_->GetStorage();
  DCHECK(storage);
  KeyValueStore args;
  args.Set<std::string>(kTypeProperty, kTypeCellular);
  std::string sim_card_id = eid.empty() ? iccid : eid;
  args.Set<std::string>(CellularService::kStorageSimCardId, sim_card_id);
  std::set<std::string> groups = storage->GetGroupsWithProperties(args);

  LOG(INFO) << __func__ << ": " << sim_card_id << ": Groups: " << groups.size();
  CellularServiceRefPtr active_service = nullptr;
  for (const std::string& group : groups) {
    std::string service_imsi, service_iccid, service_eid;
    if (!GetServiceParametersFromStorage(storage, group, &service_imsi,
                                         &service_iccid, &service_eid,
                                         /*error=*/nullptr)) {
      LOG(ERROR) << "Unable to load service properties for: " << sim_card_id
                 << ", removing old or invalid profile entry.";
      storage->DeleteGroup(group);
      continue;
    }
    DCHECK_EQ(service_eid, eid);
    CellularServiceRefPtr service = FindService(service_iccid);
    if (!service) {
      SLOG(this, 1) << "Creating Cellular service for ICCID: " << service_iccid;
      service = new CellularService(manager_, service_imsi, service_iccid,
                                    service_eid);
      service->Load(storage);
      service->SetDevice(device);
      AddService(service);
    } else {
      SLOG(this, 2) << "Cellular service exists for ICCID: " << service_iccid;
      service->SetDevice(device);
    }
    if (service_iccid == iccid)
      active_service = service;
  }
  // Ensure that a Service exists for the ICCID.
  if (!active_service) {
    SLOG(this, 1) << "No existing Cellular service with ICCID: " << iccid;
    active_service = new CellularService(manager_, imsi, iccid, eid);
    active_service->SetDevice(device);
    AddService(active_service);
  }
  return active_service;
}

void CellularServiceProvider::LoadServicesForSecondarySim(
    const std::string& eid,
    const std::string& iccid,
    const std::string& imsi,
    Cellular* device) {
  DCHECK(!iccid.empty());
  SLOG(this, 1) << __func__ << " eid: " << eid << " iccid: " << iccid;
  LoadMatchingServicesFromProfile(eid, iccid, imsi, device);
}

void CellularServiceProvider::UpdateServices(Cellular* device) {
  SLOG(this, 2) << __func__;
  for (CellularServiceRefPtr& service : services_)
    service->SetDevice(device);
}

void CellularServiceProvider::RemoveServices() {
  SLOG(this, 1) << __func__;
  while (!services_.empty())
    RemoveService(services_.back());
}

CellularServiceRefPtr CellularServiceProvider::FindService(
    const std::string& iccid) {
  const auto iter = std::find_if(
      services_.begin(), services_.end(),
      [iccid](const auto& service) { return service->iccid() == iccid; });
  if (iter != services_.end())
    return *iter;
  return nullptr;
}

void CellularServiceProvider::AddService(CellularServiceRefPtr service) {
  SLOG(this, 1) << __func__ << " with ICCID: " << service->iccid();

  // See comment in header for |profile_|.
  service->SetProfile(profile_);
  // Save any changes to device properties (iccid, eid).
  profile_->UpdateService(service);
  manager_->RegisterService(service);
  services_.push_back(service);
}

void CellularServiceProvider::RemoveService(CellularServiceRefPtr service) {
  SLOG(this, 1) << __func__ << " with ICCID: " << service->iccid();
  manager_->DeregisterService(service);
  auto iter = std::find(services_.begin(), services_.end(), service);
  if (iter == services_.end()) {
    LOG(ERROR) << "RemoveService: Not found: ";
    return;
  }
  services_.erase(iter);
}

}  // namespace shill
