// Copyright (c) 2013 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_capability_universal_cdma.h"

#include <chromeos/dbus/service_constants.h>
#include <base/stringprintf.h>
#include <base/string_number_conversions.h>
#include <base/string_util.h>

#include "shill/cellular_operator_info.h"
#include "shill/dbus_properties_proxy_interface.h"
#include "shill/error.h"
#include "shill/logging.h"
#include "shill/pending_activation_store.h"
#include "shill/proxy_factory.h"

#ifdef MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN
#error "Do not include mm-modem.h"
#endif

using base::UintToString;

using std::string;
using std::vector;

namespace shill {

namespace {

string FormattedSID(const string &sid) {
  return "[SID=" + sid + "]";
}

}  // namespace

// static
unsigned int
CellularCapabilityUniversalCDMA::friendly_service_name_id_cdma_ = 0;

CellularCapabilityUniversalCDMA::CellularCapabilityUniversalCDMA(
    Cellular *cellular,
    ProxyFactory *proxy_factory,
    ModemInfo *modem_info)
    : CellularCapabilityUniversal(cellular,
                                  proxy_factory,
                                  modem_info),
      weak_cdma_ptr_factory_(this),
      activation_state_(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
      cdma_1x_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
      cdma_evdo_registration_state_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
      nid_(0),
      sid_(0) {
  SLOG(Cellular, 2) << "Cellular capability constructed: Universal CDMA";
  // TODO(armansito): Update PRL for activation over cellular.
  // See crbug.com/197330.
}

void CellularCapabilityUniversalCDMA::InitProxies() {
  SLOG(Cellular, 2) << __func__;
  modem_cdma_proxy_.reset(
      proxy_factory()->CreateMM1ModemModemCdmaProxy(cellular()->dbus_path(),
                                                    cellular()->dbus_owner()));
  modem_cdma_proxy_->set_activation_state_callback(
      Bind(&CellularCapabilityUniversalCDMA::OnActivationStateChangedSignal,
      weak_cdma_ptr_factory_.GetWeakPtr()));
  CellularCapabilityUniversal::InitProxies();
}

void CellularCapabilityUniversalCDMA::ReleaseProxies() {
  SLOG(Cellular, 2) << __func__;
  modem_cdma_proxy_.reset();
  CellularCapabilityUniversal::ReleaseProxies();
}

void CellularCapabilityUniversalCDMA::Activate(
    const string &carrier,
    Error *error,
    const ResultCallback &callback) {
  // Currently activation over the cellular network is not supported using
  // ModemManager-next. Service activation is currently carried through over
  // non-cellular networks and only the final step of the OTA activation
  // procedure ("automatic activation") is performed by this class.
  OnUnsupportedOperation(__func__, error);
}

void CellularCapabilityUniversalCDMA::CompleteActivation(Error *error) {
  SLOG(Cellular, 2) << __func__;
  if (cellular()->state() < Cellular::kStateEnabled) {
    Error::PopulateAndLog(error, Error::kInvalidArguments,
                          "Unable to activate in state " +
                          Cellular::GetStateString(cellular()->state()));
    return;
  }
  ActivateAutomatic();
}

void CellularCapabilityUniversalCDMA::ActivateAutomatic() {
  if (activation_code_.empty()) {
    SLOG(Cellular, 2) << "OTA activation cannot be run in the presence of no "
                      << "activation code.";
    return;
  }
  PendingActivationStore::State state =
      modem_info()->pending_activation_store()->GetActivationState(
          PendingActivationStore::kIdentifierMEID, meid());
  if (state == PendingActivationStore::kStatePending) {
    SLOG(Cellular, 2) << "There's already a pending activation. Ignoring.";
    return;
  }
  if (state == PendingActivationStore::kStateActivated) {
    SLOG(Cellular, 2) << "A call to OTA activation has already completed "
                      << "successfully. Ignoring.";
    return;
  }

  // Mark as pending activation, so that shill can recover if anything fails
  // during OTA activation.
  modem_info()->pending_activation_store()->SetActivationState(
      PendingActivationStore::kIdentifierMEID,
      meid(),
      PendingActivationStore::kStatePending);

  // Initiate OTA activation.
  ResultCallback activation_callback =
    Bind(&CellularCapabilityUniversalCDMA::OnActivateReply,
         weak_cdma_ptr_factory_.GetWeakPtr(),
         ResultCallback());
  // TODO(armansito): Read the activation code from CellularOperatorInfo
  Error error;
  modem_cdma_proxy_->Activate(
      activation_code_, &error, activation_callback, kTimeoutActivate);
}

void CellularCapabilityUniversalCDMA::UpdatePendingActivationState() {
  SLOG(Cellular, 2) << __func__;
  if (IsActivated()) {
    SLOG(Cellular, 3) << "CDMA service activated. Clear store.";
    modem_info()->pending_activation_store()->RemoveEntry(
        PendingActivationStore::kIdentifierMEID, meid());
    return;
  }
  PendingActivationStore::State state =
      modem_info()->pending_activation_store()->GetActivationState(
          PendingActivationStore::kIdentifierMEID, meid());
  if (IsActivating() && state != PendingActivationStore::kStateFailureRetry) {
    SLOG(Cellular, 3) << "OTA activation in progress. Nothing to do.";
    return;
  }
  switch (state) {
    case PendingActivationStore::kStateFailureRetry:
      SLOG(Cellular, 3) << "OTA activation failed. Scheduling a retry.";
      cellular()->dispatcher()->PostTask(
          Bind(&CellularCapabilityUniversalCDMA::ActivateAutomatic,
               weak_cdma_ptr_factory_.GetWeakPtr()));
      break;
    case PendingActivationStore::kStateActivated:
      SLOG(Cellular, 3) << "OTA Activation has completed successfully. "
                        << "Waiting for activation state update to finalize.";
      break;
    default:
      break;
  }
}

bool CellularCapabilityUniversalCDMA::IsServiceActivationRequired() const {
  // If there is no online payment portal information, it's safer to assume
  // the service does not require activation.
  if (!modem_info()->cellular_operator_info())
    return false;

  const CellularService::OLP *olp =
      modem_info()->cellular_operator_info()->GetOLPBySID(UintToString(sid_));
  if (!olp)
    return false;

  // We could also use the MDN to determine whether or not the service is
  // activated, however, the CDMA ActivatonState property is a more absolute
  // and fine-grained indicator of activation status.
  return (activation_state_ == MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED);
}

bool CellularCapabilityUniversalCDMA::IsActivated() const {
  return (activation_state_ == MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED);
}

void CellularCapabilityUniversalCDMA::OnServiceCreated() {
  SLOG(Cellular, 2) << __func__;
  // TODO (armansito): Set storage identifier here  based on the superclass
  // implementation.
  UpdateServiceActivationStateProperty();
  UpdateServingOperator();
  HandleNewActivationStatus(MM_CDMA_ACTIVATION_ERROR_NONE);
  UpdatePendingActivationState();
  UpdateOLP();
}

void CellularCapabilityUniversalCDMA::UpdateServiceActivationStateProperty() {
  bool activation_required = IsServiceActivationRequired();
  cellular()->service()->SetActivateOverNonCellularNetwork(activation_required);
  string activation_state;
  if (IsActivating())
      activation_state = flimflam::kActivationStateActivating;
  else if (activation_required)
      activation_state = flimflam::kActivationStateNotActivated;
  else
      activation_state = flimflam::kActivationStateActivated;
  cellular()->service()->SetActivationState(activation_state);
}

void CellularCapabilityUniversalCDMA::UpdateOLP() {
  SLOG(Cellular,2) << __func__;
  if (!modem_info()->cellular_operator_info())
    return;

  const CellularService::OLP *result =
      modem_info()->cellular_operator_info()->GetOLPBySID(
          UintToString(sid_));
  if (!result)
    return;

  CellularService::OLP olp;
  olp.CopyFrom(*result);
  string post_data = olp.GetPostData();
  ReplaceSubstringsAfterOffset(&post_data, 0, "${esn}", esn());
  ReplaceSubstringsAfterOffset(&post_data, 0, "${mdn}", mdn());
  ReplaceSubstringsAfterOffset(&post_data, 0, "${meid}", meid());
  olp.SetPostData(post_data);
  if (cellular()->service().get())
    cellular()->service()->SetOLP(olp);
}

void CellularCapabilityUniversalCDMA::GetProperties() {
  SLOG(Cellular, 2) << __func__;
  CellularCapabilityUniversal::GetProperties();

  scoped_ptr<DBusPropertiesProxyInterface> properties_proxy(
      proxy_factory()->CreateDBusPropertiesProxy(cellular()->dbus_path(),
                                                 cellular()->dbus_owner()));
  DBusPropertiesMap properties(
      properties_proxy->GetAll(MM_DBUS_INTERFACE_MODEM_MODEMCDMA));
  OnModemCDMAPropertiesChanged(properties, vector<string>());
}

string CellularCapabilityUniversalCDMA::CreateFriendlyServiceName() {
  SLOG(Cellular, 2) << __func__ << ": " << GetRoamingStateString();

  if (provider_.GetCode().empty()) {
    UpdateOperatorInfo();
  }

  string name = provider_.GetName();
  if (!name.empty()) {
    // TODO(armansito): We may need to show the provider name in a
    // specific way if roaming.
    return name;
  }

  string code = provider_.GetCode();
  if (!code.empty()) {
    return "cellular_sid_" + code;
  }

  return base::StringPrintf("CDMANetwork%u", friendly_service_name_id_cdma_++);
}

void CellularCapabilityUniversalCDMA::UpdateOperatorInfo() {
  SLOG(Cellular, 2) << __func__;

  if (sid_ == 0 || !modem_info()->cellular_operator_info()) {
    SLOG(Cellular, 2) << "No provider is currently available.";
    provider_.SetCode("");
    return;
  }

  string sid = UintToString(sid_);
  const CellularOperatorInfo::CellularOperator *provider =
      modem_info()->cellular_operator_info()->GetCellularOperatorBySID(sid);
  if (!provider) {
    SLOG(Cellular, 2) << "CDMA provider with "
                      << FormattedSID(sid)
                      << " not found.";
    return;
  }

  if (!provider->name_list().empty()) {
    provider_.SetName(provider->name_list()[0].name);
  }
  provider_.SetCode(sid);
  provider_.SetCountry(provider->country());

  activation_code_ = provider->activation_code();

  // TODO(armansito): The CDMA interface only returns information about the
  // current serving carrier, so for now both the home provider and the
  // serving operator will be the same in case of roaming. We should figure
  // out if there is a way to (and whether or not it is necessary to)
  // determine if we're roaming.
  cellular()->set_home_provider(provider_);

  UpdateServingOperator();
}

void CellularCapabilityUniversalCDMA::UpdateServingOperator() {
  SLOG(Cellular, 2) << __func__;
  if (cellular()->service().get()) {
    cellular()->service()->SetServingOperator(cellular()->home_provider());
  }
}

void CellularCapabilityUniversalCDMA::OnActivationStateChangedSignal(
    uint32 activation_state,
    uint32 activation_error,
    const DBusPropertiesMap &status_changes) {
  SLOG(Cellular, 2) << __func__;

  activation_state_ =
      static_cast<MMModemCdmaActivationState>(activation_state);

  string value;
  if (DBusProperties::GetString(status_changes, "mdn", &value))
    set_mdn(value);
  if (DBusProperties::GetString(status_changes, "min", &value))
    set_min(value);

  SLOG(Cellular, 2) << "Activation state: "
                    << GetActivationStateString(activation_state_);

  HandleNewActivationStatus(activation_error);
  UpdatePendingActivationState();
}

void CellularCapabilityUniversalCDMA::OnActivateReply(
    const ResultCallback &callback,
    const Error &error) {
  SLOG(Cellular, 2) << __func__;
  if (error.IsSuccess()) {
    LOG(INFO) << "Activation completed successfully.";
    modem_info()->pending_activation_store()->SetActivationState(
        PendingActivationStore::kIdentifierMEID,
        meid(),
        PendingActivationStore::kStateActivated);
  } else {
    LOG(ERROR) << "Activation failed with error: " << error;
    modem_info()->pending_activation_store()->SetActivationState(
        PendingActivationStore::kIdentifierMEID,
        meid(),
        PendingActivationStore::kStateFailureRetry);
  }
  UpdatePendingActivationState();
  callback.Run(error);
}

void CellularCapabilityUniversalCDMA::HandleNewActivationStatus(uint32 error) {
  SLOG(Cellular, 2) << __func__ << "(" << error << ")";
  if (!cellular()->service().get()) {
    LOG(ERROR) << "In " << __func__ << "(): service is null.";
    return;
  }
  SLOG(Cellular, 2) << "Activation State: " << activation_state_;
  cellular()->service()->SetActivationState(
      GetActivationStateString(activation_state_));
  cellular()->service()->set_error(GetActivationErrorString(error));
  UpdateOLP();
}

// static
string CellularCapabilityUniversalCDMA::GetActivationStateString(
    uint32 state) {
  switch (state) {
    case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
      return flimflam::kActivationStateActivated;
    case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING:
      return flimflam::kActivationStateActivating;
    case MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED:
      return flimflam::kActivationStateNotActivated;
    case MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED:
      return flimflam::kActivationStatePartiallyActivated;
    default:
      return flimflam::kActivationStateUnknown;
  }
}

// static
string CellularCapabilityUniversalCDMA::GetActivationErrorString(
    uint32 error) {
  switch (error) {
    case MM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE:
      return flimflam::kErrorNeedEvdo;
    case MM_CDMA_ACTIVATION_ERROR_ROAMING:
      return flimflam::kErrorNeedHomeNetwork;
    case MM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT:
    case MM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED:
    case MM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED:
      return flimflam::kErrorOtaspFailed;
    case MM_CDMA_ACTIVATION_ERROR_NONE:
      return "";
    case MM_CDMA_ACTIVATION_ERROR_NO_SIGNAL:
    default:
      return flimflam::kErrorActivationFailed;
  }
}

void CellularCapabilityUniversalCDMA::Register(const ResultCallback &callback) {
  // TODO(armansito): Remove once 3GPP is implemented in its own class.
}

void CellularCapabilityUniversalCDMA::RegisterOnNetwork(
    const string &network_id,
    Error *error,
    const ResultCallback &callback) {
  // TODO(armansito): Remove once 3GPP is implemented in its own class.
}

bool CellularCapabilityUniversalCDMA::IsActivating() const {
  PendingActivationStore::State state =
      modem_info()->pending_activation_store()->GetActivationState(
          PendingActivationStore::kIdentifierMEID, meid());
  return (state == PendingActivationStore::kStatePending) ||
      (state == PendingActivationStore::kStateFailureRetry) ||
      (activation_state_ == MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING);
}

bool CellularCapabilityUniversalCDMA::IsRegistered() {
  return (cdma_1x_registration_state_ ==
              MM_MODEM_CDMA_REGISTRATION_STATE_HOME ||
          cdma_1x_registration_state_ ==
              MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING ||
          cdma_evdo_registration_state_ ==
              MM_MODEM_CDMA_REGISTRATION_STATE_HOME ||
          cdma_evdo_registration_state_ ==
              MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING);
}

void CellularCapabilityUniversalCDMA::SetUnregistered(bool /*searching*/) {
  cdma_1x_registration_state_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
  cdma_evdo_registration_state_ = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
}

void CellularCapabilityUniversalCDMA::RequirePIN(
    const string &pin, bool require,
    Error *error, const ResultCallback &callback) {
  // TODO(armansito): Remove once 3GPP is implemented in its own class.
}

void CellularCapabilityUniversalCDMA::EnterPIN(
    const string &pin,
    Error *error,
    const ResultCallback &callback) {
  // TODO(armansito): Remove once 3GPP is implemented in its own class.
}

void CellularCapabilityUniversalCDMA::UnblockPIN(
    const string &unblock_code,
    const string &pin,
    Error *error,
    const ResultCallback &callback) {
  // TODO(armansito): Remove once 3GPP is implemented in its own class.
}

void CellularCapabilityUniversalCDMA::ChangePIN(
    const string &old_pin, const string &new_pin,
    Error *error, const ResultCallback &callback) {
  // TODO(armansito): Remove once 3GPP is implemented in its own class.
}

void CellularCapabilityUniversalCDMA::Scan(Error *error,
                                           const ResultCallback &callback) {
  // TODO(armansito): Remove once 3GPP is implemented in its own class.
}

void CellularCapabilityUniversalCDMA::OnSimPathChanged(
    const string &sim_path) {
  // TODO(armansito): Remove once 3GPP is implemented in its own class.
}

string CellularCapabilityUniversalCDMA::GetRoamingStateString() const {
  uint32 state = cdma_evdo_registration_state_;
  if (state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
    state = cdma_1x_registration_state_;
  }
  switch (state) {
    case MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN:
    case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
      break;
    case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
      return flimflam::kRoamingStateHome;
    case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
      return flimflam::kRoamingStateRoaming;
    default:
      NOTREACHED();
  }
  return flimflam::kRoamingStateUnknown;
}

void CellularCapabilityUniversalCDMA::OnDBusPropertiesChanged(
    const string &interface,
    const DBusPropertiesMap &changed_properties,
    const vector<string> &invalidated_properties) {
  SLOG(Cellular, 2) << __func__ << "(" << interface << ")";
  if (interface == MM_DBUS_INTERFACE_MODEM_MODEMCDMA) {
    OnModemCDMAPropertiesChanged(changed_properties, invalidated_properties);
  } else {
    CellularCapabilityUniversal::OnDBusPropertiesChanged(
        interface, changed_properties, invalidated_properties);
  }
}

void CellularCapabilityUniversalCDMA::OnModemCDMAPropertiesChanged(
    const DBusPropertiesMap &properties,
    const std::vector<std::string> &/*invalidated_properties*/) {
  SLOG(Cellular, 2) << __func__;
  string str_value;
  if (DBusProperties::GetString(properties,
                                MM_MODEM_MODEMCDMA_PROPERTY_MEID,
                                &str_value))
    set_meid(str_value);
  if (DBusProperties::GetString(properties,
                                MM_MODEM_MODEMCDMA_PROPERTY_ESN,
                                &str_value))
    set_esn(str_value);

  uint32_t sid = sid_;
  uint32_t nid = nid_;
  MMModemCdmaRegistrationState state_1x = cdma_1x_registration_state_;
  MMModemCdmaRegistrationState state_evdo = cdma_evdo_registration_state_;
  bool registration_changed = false;
  uint32_t uint_value;
  if (DBusProperties::GetUint32(
      properties,
      MM_MODEM_MODEMCDMA_PROPERTY_CDMA1XREGISTRATIONSTATE,
      &uint_value)) {
    state_1x = static_cast<MMModemCdmaRegistrationState>(uint_value);
    registration_changed = true;
  }
  if (DBusProperties::GetUint32(
      properties,
      MM_MODEM_MODEMCDMA_PROPERTY_EVDOREGISTRATIONSTATE,
      &uint_value)) {
    state_evdo = static_cast<MMModemCdmaRegistrationState>(uint_value);
    registration_changed = true;
  }
  if (DBusProperties::GetUint32(
      properties,
      MM_MODEM_MODEMCDMA_PROPERTY_SID,
      &uint_value)) {
    sid = uint_value;
    registration_changed = true;
  }
  if (DBusProperties::GetUint32(
      properties,
      MM_MODEM_MODEMCDMA_PROPERTY_NID,
      &uint_value)) {
    nid = uint_value;
    registration_changed = true;
  }
  if (DBusProperties::GetUint32(
      properties,
      MM_MODEM_MODEMCDMA_PROPERTY_ACTIVATIONSTATE,
      &uint_value)) {
    activation_state_ = static_cast<MMModemCdmaActivationState>(uint_value);
    HandleNewActivationStatus(MM_CDMA_ACTIVATION_ERROR_NONE);
  }
  if (registration_changed)
    OnCDMARegistrationChanged(state_1x, state_evdo, sid, nid);
}

void CellularCapabilityUniversalCDMA::OnCDMARegistrationChanged(
      MMModemCdmaRegistrationState state_1x,
      MMModemCdmaRegistrationState state_evdo,
      uint32_t sid, uint32_t nid) {
  SLOG(Cellular, 2) << __func__
                    << ": state_1x=" << state_1x
                    << ", state_evdo=" << state_evdo;
  cdma_1x_registration_state_ = state_1x;
  cdma_evdo_registration_state_ = state_evdo;
  sid_ = sid;
  nid_ = nid;
  UpdateOperatorInfo();
  cellular()->HandleNewRegistrationState();
}

}  // namespace shill
