// Copyright 2018 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_capability_classic.h"

#include <base/bind.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/cellular/cellular.h"
#include "shill/cellular/modem_gobi_proxy_interface.h"
#include "shill/control_interface.h"
#include "shill/error.h"
#include "shill/logging.h"
#include "shill/property_accessor.h"

using base::Bind;
using base::Closure;
using std::string;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kCellular;
static string ObjectID(CellularCapabilityClassic* c) {
  return c->cellular()->GetRpcIdentifier();
}
}

const char CellularCapabilityClassic::kConnectPropertyApn[] = "apn";
const char CellularCapabilityClassic::kConnectPropertyApnUsername[] =
    "username";
const char CellularCapabilityClassic::kConnectPropertyApnPassword[] =
    "password";
const char CellularCapabilityClassic::kConnectPropertyHomeOnly[] = "home_only";
const char CellularCapabilityClassic::kConnectPropertyPhoneNumber[] = "number";
const char CellularCapabilityClassic::kModemPropertyEnabled[] = "Enabled";
const int CellularCapabilityClassic::kTimeoutSetCarrierMilliseconds = 120000;

static Cellular::ModemState ConvertClassicToModemState(uint32_t classic_state) {
  ModemClassicState cstate = static_cast<ModemClassicState>(classic_state);
  switch (cstate) {
    case kModemClassicStateUnknown:
      return Cellular::kModemStateUnknown;
    case kModemClassicStateDisabled:
      return Cellular::kModemStateDisabled;
    case kModemClassicStateDisabling:
      return Cellular::kModemStateDisabling;
    case kModemClassicStateEnabling:
      return Cellular::kModemStateEnabling;
    case kModemClassicStateEnabled:
      return Cellular::kModemStateEnabled;
    case kModemClassicStateSearching:
      return Cellular::kModemStateSearching;
    case kModemClassicStateRegistered:
      return Cellular::kModemStateRegistered;
    case kModemClassicStateDisconnecting:
      return Cellular::kModemStateDisconnecting;
    case kModemClassicStateConnecting:
      return Cellular::kModemStateConnecting;
    case kModemClassicStateConnected:
      return Cellular::kModemStateConnected;
    default:
      return Cellular::kModemStateUnknown;
  }
}

CellularCapabilityClassic::CellularCapabilityClassic(Cellular* cellular,
                                                     ModemInfo* modem_info)
    : CellularCapability(cellular, modem_info), weak_ptr_factory_(this) {
  // This class is currently instantiated only for Gobi modems so setup the
  // supported carriers list appropriately and expose it over RPC.
  cellular->set_supported_carriers({kCarrierGenericUMTS,
                                    kCarrierSprint,
                                    kCarrierVerizon});
}

CellularCapabilityClassic::~CellularCapabilityClassic() {}

void CellularCapabilityClassic::InitProxies() {
  SLOG(this, 2) << __func__;
  proxy_ = control_interface()->CreateModemProxy(cellular()->dbus_path(),
                                                 cellular()->dbus_service());
  simple_proxy_ = control_interface()->CreateModemSimpleProxy(
      cellular()->dbus_path(), cellular()->dbus_service());
  proxy_->set_state_changed_callback(
      Bind(&CellularCapabilityClassic::OnModemStateChangedSignal,
           weak_ptr_factory_.GetWeakPtr()));
}

void CellularCapabilityClassic::ReleaseProxies() {
  SLOG(this, 2) << __func__;
  proxy_.reset();
  simple_proxy_.reset();
  gobi_proxy_.reset();
}

bool CellularCapabilityClassic::AreProxiesInitialized() const {
  return (proxy_.get() && simple_proxy_.get() && gobi_proxy_.get());
}

void CellularCapabilityClassic::FinishEnable(const ResultCallback& callback) {
  // Normally, running the callback is the last thing done in a method.
  // In this case, we do it first, because we want to make sure that
  // the device is marked as Enabled before the registration state is
  // handled. See comment in Cellular::HandleNewRegistrationState.
  callback.Run(Error());
  GetRegistrationState();
  GetSignalQuality();
  // We expect the modem to start scanning after it has been enabled.
  // Change this if this behavior is no longer the case in the future.
  modem_info()->metrics()->NotifyDeviceEnableFinished(
      cellular()->interface_index());
  modem_info()->metrics()->NotifyDeviceScanStarted(
      cellular()->interface_index());
}

void CellularCapabilityClassic::FinishDisable(const ResultCallback& callback) {
  modem_info()->metrics()->NotifyDeviceDisableFinished(
      cellular()->interface_index());
  ReleaseProxies();
  callback.Run(Error());
}

void CellularCapabilityClassic::RunNextStep(CellularTaskList* tasks) {
  CHECK(!tasks->empty());
  SLOG(this, 2) << __func__ << ": " << tasks->size() << " remaining tasks";
  Closure task = (*tasks)[0];
  tasks->erase(tasks->begin());
  cellular()->dispatcher()->PostTask(FROM_HERE, task);
}

void CellularCapabilityClassic::StepCompletedCallback(
    const ResultCallback& callback,
    bool ignore_error,
    CellularTaskList* tasks,
    const Error& error) {
  if ((ignore_error || error.IsSuccess()) && !tasks->empty()) {
    RunNextStep(tasks);
    return;
  }
  delete tasks;
  if (!callback.is_null())
    callback.Run(error);
}

// always called from an async context
void CellularCapabilityClassic::EnableModem(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  CHECK(!callback.is_null());
  Error error;
  modem_info()->metrics()->NotifyDeviceEnableStarted(
      cellular()->interface_index());
  proxy_->Enable(true, &error, callback, kTimeoutEnable);
  if (error.IsFailure())
    callback.Run(error);
}

// always called from an async context
void CellularCapabilityClassic::DisableModem(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  CHECK(!callback.is_null());
  Error error;
  modem_info()->metrics()->NotifyDeviceDisableStarted(
      cellular()->interface_index());
  proxy_->Enable(false, &error, callback, kTimeoutEnable);
  if (error.IsFailure())
      callback.Run(error);
}

// always called from an async context
void CellularCapabilityClassic::GetModemStatus(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  CHECK(!callback.is_null());
  KeyValueStoreCallback cb = Bind(
      &CellularCapabilityClassic::OnGetModemStatusReply,
      weak_ptr_factory_.GetWeakPtr(), callback);
  Error error;
  simple_proxy_->GetModemStatus(&error, cb, kTimeoutDefault);
  if (error.IsFailure())
      callback.Run(error);
}

// always called from an async context
void CellularCapabilityClassic::GetModemInfo(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  CHECK(!callback.is_null());
  ModemInfoCallback cb = Bind(&CellularCapabilityClassic::OnGetModemInfoReply,
                              weak_ptr_factory_.GetWeakPtr(), callback);
  Error error;
  proxy_->GetModemInfo(&error, cb, kTimeoutDefault);
  if (error.IsFailure())
      callback.Run(error);
}

void CellularCapabilityClassic::StopModem(Error* error,
                                          const ResultCallback& callback) {
  SLOG(this, 2) << __func__;

  CellularTaskList* tasks = new CellularTaskList();
  ResultCallback cb =
      Bind(&CellularCapabilityClassic::StepCompletedCallback,
           weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
  ResultCallback cb_ignore_error =
      Bind(&CellularCapabilityClassic::StepCompletedCallback,
           weak_ptr_factory_.GetWeakPtr(), callback, true, tasks);
  // TODO(ers): We can skip the call to Disconnect if the modem has
  // told us that the modem state is Disabled or Registered.
  tasks->push_back(Bind(&CellularCapabilityClassic::Disconnect,
                        weak_ptr_factory_.GetWeakPtr(), nullptr,
                        cb_ignore_error));
  // TODO(ers): We can skip the call to Disable if the modem has
  // told us that the modem state is Disabled.
  tasks->push_back(Bind(&CellularCapabilityClassic::DisableModem,
                        weak_ptr_factory_.GetWeakPtr(), cb));
  tasks->push_back(Bind(&CellularCapabilityClassic::FinishDisable,
                        weak_ptr_factory_.GetWeakPtr(), cb));

  RunNextStep(tasks);
}

void CellularCapabilityClassic::Connect(const KeyValueStore& properties,
                                        Error* error,
                                        const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  simple_proxy_->Connect(properties, error, callback, kTimeoutConnect);
}

void CellularCapabilityClassic::Disconnect(Error* error,
                                           const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  if (proxy_)
    proxy_->Disconnect(error, callback, kTimeoutDisconnect);
  else
    LOG(ERROR) << "No proxy found in disconnect.";
}

void CellularCapabilityClassic::SetCarrier(const string& carrier,
                                           Error* error,
                                           const ResultCallback& callback) {
  LOG(INFO) << __func__ << "(" << carrier << ")";
  if (!gobi_proxy_) {
    gobi_proxy_ = control_interface()->CreateModemGobiProxy(
        cellular()->dbus_path(), cellular()->dbus_service());
  }
  CHECK(error);
  gobi_proxy_->SetCarrier(carrier, error, callback,
                          kTimeoutSetCarrierMilliseconds);
}

void CellularCapabilityClassic::OnPropertiesChanged(
    const std::string& interface,
    const KeyValueStore& changed_properties,
    const std::vector<std::string>& invalidated_properties) {
  SLOG(this, 2) << __func__;
  // This solves a bootstrapping problem: If the modem is not yet
  // enabled, there are no proxy objects associated with the capability
  // object, so modem signals like StateChanged aren't seen. By monitoring
  // changes to the Enabled property via the ModemManager, we're able to
  // get the initialization process started, which will result in the
  // creation of the proxy objects.
  //
  // We handle all state changes to ENABLED from a disabled state (including,
  // UNKNOWN) through Cellular::OnModemStateChanged. This will try to enable
  // the device regardless of whether it has been registered with the Manager.
  //
  // All other state changes are handled from OnModemStateChangedSignal.
  if (changed_properties.ContainsBool(kModemPropertyEnabled)) {
    bool enabled = changed_properties.GetBool(kModemPropertyEnabled);
    SLOG(this, 2) << "Property \"Enabled\" changed: " << enabled;
    Cellular::ModemState prev_modem_state = cellular()->modem_state();
    if (!Cellular::IsEnabledModemState(prev_modem_state)) {
      cellular()->OnModemStateChanged(
          enabled ? Cellular::kModemStateEnabled :
                    Cellular::kModemStateDisabled);
    }
  }
}

void CellularCapabilityClassic::OnGetModemStatusReply(
    const ResultCallback& callback,
    const KeyValueStore& props,
    const Error& error) {
  SLOG(this, 2) << __func__ << " error " << error;
  if (error.IsSuccess()) {
    if (props.ContainsString("carrier")) {
      string carrier = props.GetString("carrier");
      cellular()->set_carrier(carrier);
      cellular()->home_provider_info()->UpdateOperatorName(carrier);
    }
    if (props.ContainsString("meid")) {
      cellular()->set_meid(props.GetString("meid"));
    }
    if (props.ContainsString("imei")) {
     cellular()->set_imei(props.GetString("imei"));
    }
    if (props.ContainsString(kModemPropertyIMSI)) {
      string imsi = props.GetString(kModemPropertyIMSI);
      cellular()->set_imsi(imsi);
      cellular()->home_provider_info()->UpdateIMSI(imsi);
      // We do not currently obtain the IMSI OTA at all. Provide the IMSI from
      // the SIM to the serving operator as well to aid in MVNO identification.
      cellular()->serving_operator_info()->UpdateIMSI(imsi);
    }
    if (props.ContainsString("esn")) {
      cellular()->set_esn(props.GetString("esn"));
    }
    if (props.ContainsString("mdn")) {
      cellular()->set_mdn(props.GetString("mdn"));
    }
    if (props.ContainsString("min")) {
      cellular()->set_min(props.GetString("min"));
    }
    if (props.ContainsString("firmware_revision")) {
      cellular()->set_firmware_revision(props.GetString("firmware_revision"));
    }
    UpdateStatus(props);
  }
  callback.Run(error);
}

void CellularCapabilityClassic::UpdateStatus(
    const KeyValueStore& properties) {
  SLOG(this, 3) << __func__;
}

void CellularCapabilityClassic::OnGetModemInfoReply(
    const ResultCallback& callback,
    const std::string& manufacturer,
    const std::string& modem,
    const std::string& version,
    const Error& error) {
  SLOG(this, 2) << __func__ << "(" << error << ")";
  if (error.IsSuccess()) {
    cellular()->set_manufacturer(manufacturer);
    cellular()->set_model_id(modem);
    cellular()->set_hardware_revision(version);
    SLOG(this, 2) << __func__ << ": " << manufacturer << ", " << modem << ", "
                  << version;
  }
  callback.Run(error);
}

void CellularCapabilityClassic::OnModemStateChangedSignal(
    uint32_t old_state, uint32_t new_state, uint32_t reason) {
  SLOG(this, 2) << __func__ << "(" << old_state << ", " << new_state << ", "
                << reason << ")";
  cellular()->OnModemStateChanged(ConvertClassicToModemState(new_state));
}

}  // namespace shill
