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

#include <algorithm>
#include <array>
#include <utility>
#include <base/bind.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <glib.h>
#include <gio/gio.h>
#include <gmodule.h>
#include <gio/gunixsocketaddress.h>
#include <libmbim-glib/libmbim-glib.h>
#include "hermes/apdu.h"
#include "hermes/euicc_manager_interface.h"
#include "hermes/hermes_common.h"
#include "hermes/modem_mbim.h"
#include "hermes/sgp_22.h"
#include "hermes/type_traits.h"

namespace {

const guint kMbimResponseTimeout = 30;
constexpr int kMbimMessageSuccess = 144;
// Application identifier for the eUICC's SIM EID
const std::array<uint8_t, 12> kMbimEidReqApdu = {
    0x81, 0xE2, 0x91, 0x00, 0x06, 0xBF, 0x3E, 0x03, 0x5C, 0x01, 0x5A, 0x00,
};

}  // namespace

namespace hermes {

/* static */
std::unique_ptr<ModemMbim> ModemMbim::Create(Logger* logger,
                                             Executor* executor) {
  VLOG(2) << __func__;
  GFile* file = NULL;
  const gchar* const path = "/dev/cdc-wdm0";
  file = g_file_new_for_path(path);
  if (file == NULL) {
    LOG(ERROR) << __func__ << " :No file exist";
    return nullptr;
  }
  return std::unique_ptr<ModemMbim>(new ModemMbim(file, logger, executor));
}

ModemMbim::ModemMbim(GFile* file, Logger* logger, Executor* executor)
    : Modem<MbimCmd>(logger, executor),
      logical_slot_(0),
      channel_(kInvalidChannel),
      pending_response_(false),
      ready_state_(MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED),
      file_(file),
      is_ready_state_valid(false),
      weak_factory_(this) {}

ModemMbim::~ModemMbim() {
  VLOG(2) << "~ModemMbim Destructor++";
  Shutdown();
}

void ModemMbim::Initialize(EuiccManagerInterface* euicc_manager,
                           ResultCallback cb) {
  LOG(INFO) << __func__;
  CHECK(current_state_ == State::kMbimUninitialized);
  retry_initialization_callback_.Reset();
  euicc_manager_ = euicc_manager;
  init_done_cb_ = std::move(cb);
  current_state_.Transition(State::kMbimInitializeStarted);
  mbim_device_new(file_, /* cancellable */ NULL,
                  (GAsyncReadyCallback)MbimCreateNewDeviceCb, this);
}

void ModemMbim::Shutdown() {
  LOG(INFO) << __func__;
  if (device_) {
    if (g_signal_handler_is_connected(device_.get(), indication_id_)) {
      g_signal_handler_disconnect(device_.get(), indication_id_);
    }
    device_.reset();
  }
  channel_ = kInvalidChannel;
  pending_response_ = false;
  ready_state_ = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED,
  current_state_.Transition(State::kMbimUninitialized);
}

void ModemMbim::TransmitFromQueue() {
  VLOG(2) << __func__ << "++";
  if (tx_queue_.empty() || pending_response_ ||
      retry_initialization_callback_) {
    return;
  }

  auto mbim_cmd = tx_queue_[0].msg_.get();
  switch (mbim_cmd->mbim_type()) {
    case MbimCmd::MbimType::kMbimOpenLogicalChannel:
      TransmitMbimOpenLogicalChannel();
      break;
    case MbimCmd::MbimType::kMbimCloseLogicalChannel:
      TransmitMbimCloseChannel();
      break;
    case MbimCmd::MbimType::kMbimSendApdu:
      TransmitMbimSendApdu(&tx_queue_[0]);
      break;
    case MbimCmd::MbimType::kMbimSubscriberStatusReady:
      TransmitSubscriberReadyStatusQuery();
      break;
    case MbimCmd::MbimType::kMbimDeviceCaps:
      TransmitMbimLoadCurrentCapabilities();
      break;
    case MbimCmd::MbimType::kMbimSendEidApdu:
      TransmitMbimSendEidApdu();
      break;
    default:
      break;
  }
}

std::unique_ptr<MbimCmd> ModemMbim::GetTagForSendApdu() {
  return std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimSendApdu);
}

void ModemMbim::ProcessMbimResult(int err) {
  if (tx_queue_.empty()) {
    VLOG(2) << __func__ << " :Queue is Empty";
    return;
  }
  // pop before running the callback since the callback might change the state
  // of the queue.
  auto cb_ = std::move(tx_queue_[0].cb_);
  tx_queue_.pop_front();
  if (!cb_.is_null()) {
    std::move(cb_).Run(err);
  }
}

/* static */
void ModemMbim::MbimCreateNewDeviceCb(GObject* source,
                                      GAsyncResult* res,
                                      ModemMbim* modem_mbim) {
  /* Open the device */
  VLOG(2) << __func__;
  g_autoptr(GError) error = NULL;
  glib_bridge::ScopedGObject<MbimDevice> mbimdevice(
      mbim_device_new_finish(res, &error));
  modem_mbim->device_ = std::move(mbimdevice);
  if (!modem_mbim->device_.get() || error != NULL) {
    LOG(WARNING) << "Failed due to error: " << error->message;
    modem_mbim->RetryInitialization(std::move(modem_mbim->init_done_cb_));
    return;
  }
  mbim_device_open_full(modem_mbim->device_.get(), MBIM_DEVICE_OPEN_FLAGS_PROXY,
                        kMbimResponseTimeout, /* cancellable */ NULL,
                        (GAsyncReadyCallback)MbimDeviceOpenReadyCb, modem_mbim);
}

/* static */
void ModemMbim::MbimDeviceOpenReadyCb(MbimDevice* device,
                                      GAsyncResult* res,
                                      ModemMbim* modem_mbim) {
  VLOG(2) << __func__ << "++";
  g_autoptr(GError) error = NULL;
  if (!mbim_device_open_finish(device, res, &error)) {
    LOG(ERROR) << "Failed  due to error: " << error->message;
    modem_mbim->RetryInitialization(std::move(modem_mbim->init_done_cb_));
    return;
  }
  modem_mbim->indication_id_ = g_signal_connect(
      modem_mbim->device_.get(), MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
      G_CALLBACK(ClientIndicationCb), modem_mbim);
  LOG(INFO) << "Mbim Device is ready, complete the initialization process";
  auto get_imei = base::BindOnce(&ModemMbim::QueryCurrentMbimCapabilities,
                                 modem_mbim->weak_factory_.GetWeakPtr());

  modem_mbim->tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), modem_mbim->AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimSubscriberStatusReady),
       base::BindOnce(&ModemMbim::RunNextStepOrRetry,
                      modem_mbim->weak_factory_.GetWeakPtr(),
                      std::move(get_imei),
                      std::move(modem_mbim->init_done_cb_))});
  modem_mbim->TransmitFromQueue();
}

void ModemMbim::TransmitSubscriberReadyStatusQuery() {
  g_autoptr(MbimMessage) message = NULL;
  VLOG(2) << __func__;
  message = mbim_message_subscriber_ready_status_query_new(NULL);
  if (!message) {
    LOG(ERROR) << "Mbim message creation failed";
    ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)SubscriberReadyStatusRspCb, this);
}

void ModemMbim::TransmitMbimLoadCurrentCapabilities() {
  g_autoptr(MbimMessage) message = NULL;
  VLOG(2) << __func__;
  message = mbim_message_device_caps_query_new(/* error */ NULL);
  if (!message) {
    LOG(ERROR) << __func__ << " :Mbim message creation failed";
    ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)DeviceCapsQueryReady, this);
}

void ModemMbim::TransmitMbimCloseChannel() {
  g_autoptr(MbimMessage) message = NULL;
  g_autoptr(GError) error = NULL;
  VLOG(2) << __func__;
  message = mbim_message_ms_uicc_low_level_access_close_channel_set_new(
      channel_,
      /*channelGroupId*/ 1, &error);
  if (!message) {
    LOG(ERROR) << "Mbim message creation failed:" << error->message;
    ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  pending_response_ = true;
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)UiccLowLevelAccessCloseChannelSetCb,
                      this);
}

void ModemMbim::TransmitMbimOpenLogicalChannel() {
  VLOG(2) << __func__;
  guint8 appId[16];
  guint32 appIdSize = kAidIsdr.size();
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) message = NULL;
  std::copy(kAidIsdr.begin(), kAidIsdr.end(), appId);
  message = mbim_message_ms_uicc_low_level_access_open_channel_set_new(
      appIdSize, appId, /* selectP2arg */ 4, /* channelGroupId */ 1, &error);
  if (!message) {
    LOG(ERROR) << __func__ << ": Mbim Message Creation Failed";
    ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  pending_response_ = true;
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)UiccLowLevelAccessOpenChannelSetCb,
                      this);
}

void ModemMbim::TransmitMbimSendEidApdu() {
  VLOG(2) << __func__;
  uint8_t eid_apduCmd[kMaxApduLen];
  guint32 kMbimEidReqApduSize = kMbimEidReqApdu.size();
  g_autoptr(MbimMessage) message = NULL;
  MbimUiccSecureMessaging secure_messaging = MBIM_UICC_SECURE_MESSAGING_NONE;
  MbimUiccClassByteType class_byte_type = MBIM_UICC_CLASS_BYTE_TYPE_EXTENDED;
  std::copy(kMbimEidReqApdu.begin(), kMbimEidReqApdu.end(), eid_apduCmd);
  message = (mbim_message_ms_uicc_low_level_access_apdu_set_new(
      channel_, secure_messaging, class_byte_type, kMbimEidReqApduSize,
      eid_apduCmd, NULL));
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)UiccLowLevelAccessApduEidParse,
                      this);
}

void ModemMbim::TransmitMbimSendApdu(TxElement* tx_element) {
  g_autoptr(MbimMessage) message = NULL;
  MbimUiccSecureMessaging secure_messaging = MBIM_UICC_SECURE_MESSAGING_NONE;
  MbimUiccClassByteType class_byte_type = MBIM_UICC_CLASS_BYTE_TYPE_EXTENDED;
  uint8_t* fragment;
  size_t apdu_len = 0;
  uint8_t apduCmd[kMaxApduLen] = {0};
  VLOG(2) << __func__;
  ApduTxInfo* apdu = static_cast<ApduTxInfo*>(tx_element->info_.get());
  size_t fragment_size = apdu->apdu_.GetNextFragment(&fragment);
  VLOG(2) << "Fragment size" << fragment_size;
  apdu_len = fragment_size;
  std::copy(fragment, fragment + fragment_size, apduCmd);
  apduCmd[apdu_len++] = 0x00;

  VLOG(2) << "APDU fragment #"
          << " bytes): " << base::HexEncode(apduCmd, apdu_len);
  VLOG(2) << "Send the apdu over channel number: " << channel_;
  pending_response_ = true;
  message = (mbim_message_ms_uicc_low_level_access_apdu_set_new(
      channel_, secure_messaging, class_byte_type, apdu_len, apduCmd, NULL));
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /* cancellable */ NULL,
                      (GAsyncReadyCallback)UiccLowLevelAccessApduResponseParse,
                      this);

  return;
}

void ModemMbim::QueryCurrentMbimCapabilities(ResultCallback cb) {
  auto reacquire_channel = base::BindOnce(&ModemMbim::GetEidStepCloseChannel,
                                          weak_factory_.GetWeakPtr());
  tx_queue_.push_front(
      {std::make_unique<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimDeviceCaps),
       base::BindOnce(&ModemMbim::RunNextStepOrRetry,
                      weak_factory_.GetWeakPtr(), std::move(reacquire_channel),
                      std::move(cb))});
  TransmitFromQueue();
}

void ModemMbim::AcquireChannel(base::OnceCallback<void(int)> cb) {
  LOG(INFO) << __func__;
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimOpenLogicalChannel),
       std::move(cb)});
  TransmitFromQueue();
}

void ModemMbim::ReacquireChannel(const uint32_t physical_slot,
                                 ResultCallback cb) {
  LOG(INFO) << __func__ << " with physical_slot: " << physical_slot;
  auto acquire_channel =
      base::BindOnce(&ModemMbim::AcquireChannel, weak_factory_.GetWeakPtr());
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimCloseLogicalChannel),
       base::BindOnce(&RunNextStep, std::move(acquire_channel),
                      std::move(cb))});
  TransmitFromQueue();
}

void ModemMbim::GetEidFromSim(ResultCallback cb) {
  VLOG(2) << __func__;
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimSendEidApdu),
       std::move(cb)});
  TransmitFromQueue();
}

void ModemMbim::GetEidStepCloseChannel(ResultCallback cb) {
  auto open_channel = base::BindOnce(&ModemMbim::GetEidStepOpenChannel,
                                     weak_factory_.GetWeakPtr());
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimCloseLogicalChannel),
       base::BindOnce(&RunNextStep, std::move(open_channel), std::move(cb))});
  TransmitFromQueue();
}

void ModemMbim::GetEidStepOpenChannel(ResultCallback cb) {
  VLOG(2) << __func__;

  auto get_eid_from_sim =
      base::BindOnce(&ModemMbim::GetEidFromSim, weak_factory_.GetWeakPtr());
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimOpenLogicalChannel),
       base::BindOnce(&ModemMbim::RunNextStepOrRetry,
                      weak_factory_.GetWeakPtr(), std::move(get_eid_from_sim),
                      std::move(cb))});
  TransmitFromQueue();
}

/* static */
void ModemMbim::SubscriberReadyStatusRspCb(MbimDevice* device,
                                           GAsyncResult* res,
                                           ModemMbim* modem_mbim) {
  g_autoptr(MbimMessage) response = NULL;
  VLOG(2) << __func__;
  g_autoptr(GError) error = NULL;
  MbimSubscriberReadyState ready_state =
      MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
  g_autofree gchar* subscriber_id = NULL;
  response = mbim_device_command_finish(device, res, &error);
  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_subscriber_ready_status_response_parse(
          response, &ready_state, &subscriber_id,
          /* sim_iccid */ NULL,
          /* ready_info */ NULL,
          /* telephone_numbers_count */ NULL,
          /* telephone_numbers */ NULL, &error)) {
    modem_mbim->ready_state_ = ready_state;
    LOG(INFO) << "Current Sim status: " << ready_state;
    if (ready_state == MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED) {
      VLOG(2) << "Sim not inserted";
      modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
      return;
    }
    if (ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED)
      VLOG(2) << "Profile already enabled";

    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  LOG(ERROR) << __func__ << "Failed due to error: " << error->message;
  modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
}

/* static */
void ModemMbim::DeviceCapsQueryReady(MbimDevice* device,
                                     GAsyncResult* res,
                                     ModemMbim* modem_mbim) {
  g_autoptr(MbimMessage) response = NULL;
  g_autoptr(GError) error = NULL;
  g_autofree gchar* caps_device_id = NULL;
  VLOG(2) << __func__;
  response = mbim_device_command_finish(device, res, &error);
  if (!response ||
      !mbim_message_response_get_result(
          response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) ||
      !mbim_message_device_caps_response_parse(response, NULL, /* device_type */
                                               NULL, /* cellular class  */
                                               NULL, /* voice_class  */
                                               NULL, /* sim_class  */
                                               NULL, /* data_class */
                                               NULL, /* sms_caps */
                                               NULL, /* ctrl_caps */
                                               NULL, /* max_sessions */
                                               NULL, /* custom_data_class */
                                               &caps_device_id,
                                               NULL, /* firmware_info */
                                               NULL, /* hardware_info */
                                               &error)) {
    modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  modem_mbim->imei_ = caps_device_id;
  VLOG(2) << "IMEI received from modem: " << modem_mbim->imei_;
  modem_mbim->ProcessMbimResult(kModemSuccess);
}

/* static */
void ModemMbim::UiccLowLevelAccessCloseChannelSetCb(MbimDevice* device,
                                                    GAsyncResult* res,
                                                    ModemMbim* modem_mbim) {
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) response = NULL;
  guint32 status;
  LOG(INFO) << __func__;
  response = mbim_device_command_finish(device, res, &error);
  modem_mbim->pending_response_ = false;

  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_ms_uicc_low_level_access_close_channel_response_parse(
          response, &status, &error)) {
    modem_mbim->channel_ = kInvalidChannel;
    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  if (g_error_matches(error, MBIM_STATUS_ERROR,
                      MBIM_STATUS_ERROR_OPERATION_NOT_ALLOWED)) {
    LOG(INFO) << "Operation not allowed from modem: " << error->message;
  } else {
    LOG(INFO) << "Channel could not be closed: " << error->message;
  }
  modem_mbim->ProcessMbimResult(kModemSuccess);
}

/* static */
void ModemMbim::UiccLowLevelAccessOpenChannelSetCb(MbimDevice* device,
                                                   GAsyncResult* res,
                                                   ModemMbim* modem_mbim) {
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) response = NULL;
  guint32 status;
  guint32 chl;
  guint32 rsp_size;
  const guint8* rsp = NULL;
  LOG(INFO) << __func__;
  response = mbim_device_command_finish(device, res, &error);
  modem_mbim->pending_response_ = false;
  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_ms_uicc_low_level_access_open_channel_response_parse(
          response, &status, &chl, &rsp_size, &rsp, &error)) {
    if (status != kMbimMessageSuccess) {
      LOG(ERROR) << "Failed to open channel: " << error->message;
      modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
      return;
    }
    VLOG(2) << "Successfully opened channel: " << chl;
    modem_mbim->channel_ = chl;
    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  if (g_error_matches(error, MBIM_STATUS_ERROR,
                      MBIM_STATUS_ERROR_OPERATION_NOT_ALLOWED)) {
    LOG(ERROR) << "Operation not allowed from modem: " << error->message;
  } else {
    LOG(ERROR) << "Failed to open channel" << error->message;
  }
  modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
}

/* static */
void ModemMbim::UiccLowLevelAccessApduEidParse(MbimDevice* device,
                                               GAsyncResult* res,
                                               ModemMbim* modem_mbim) {
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) response = NULL;
  guint32 status;
  guint32 response_size = 0;
  const guint8* out_response = NULL;
  std::vector<uint8_t> kGetEidDgiTag = {0xBF, 0x3E, 0x12, 0x5A, 0x10};
  response = mbim_device_command_finish(device, res, &error);
  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_ms_uicc_low_level_access_apdu_response_parse(
          response, &status, &response_size, &out_response, &error)) {
    if (response_size < 2 || out_response[0] != kGetEidDgiTag[0] ||
        out_response[1] != kGetEidDgiTag[1]) {
      modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
      return;
    }

    VLOG(2) << "Adding to payload from APDU response (" << response_size
            << " bytes)"
            << base::HexEncode(&out_response[kGetEidDgiTag.size()],
                               response_size - kGetEidDgiTag.size());
    for (int j = kGetEidDgiTag.size(); j < response_size; j++) {
      modem_mbim->eid_ += bcd_chars[(out_response[j] >> 4) & 0xF];
      modem_mbim->eid_ += bcd_chars[out_response[j] & 0xF];
    }
    LOG(INFO) << "EID for physical slot: " << modem_mbim->logical_slot_ + 1
              << " is " << modem_mbim->eid_;
    if (modem_mbim->current_state_ == State::kMbimInitializeStarted)
      modem_mbim->current_state_.Transition(State::kMbimStarted);
    modem_mbim->euicc_manager_->OnEuiccUpdated(
        modem_mbim->logical_slot_ + 1,
        EuiccSlotInfo(modem_mbim->logical_slot_, std::move(modem_mbim->eid_)));
    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  LOG(INFO) << "Could not find eSIM";
  modem_mbim->euicc_manager_->OnEuiccRemoved(modem_mbim->logical_slot_ + 1);
  modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
  return;
}

/* static */
void ModemMbim::UiccLowLevelAccessApduResponseParse(MbimDevice* device,
                                                    GAsyncResult* res,
                                                    ModemMbim* modem_mbim) {
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) response = NULL;
  guint32 status;
  guint32 response_size = 0;
  const guint8* out_response;
  CHECK(modem_mbim->tx_queue_.size());
  // Ensure that the queued element is for a kSendApdu command
  TxInfo* base_info = modem_mbim->tx_queue_[0].info_.get();
  CHECK(base_info);
  static ResponseApdu payload;
  ApduTxInfo* info = static_cast<ApduTxInfo*>(base_info);
  response = mbim_device_command_finish(device, res, &error);
  modem_mbim->pending_response_ = false;
  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_ms_uicc_low_level_access_apdu_response_parse(
          response, &status, &response_size, &out_response, &error)) {
    VLOG(2) << "Adding to payload from APDU response (" << response_size
            << " bytes): " << base::HexEncode(out_response, response_size);

    payload.AddData(out_response, response_size);
    if (payload.MorePayloadIncoming()) {
      // Make the next transmit operation be a request for more APDU data
      info->apdu_ = payload.CreateGetMoreCommand(/*is_extended_apdu*/ false);
      return;
    }
    if (info->apdu_.HasMoreFragments()) {
      // Send next fragment of APDU
      VLOG(2) << "Sending next APDU fragment";
      modem_mbim->TransmitFromQueue();
      return;
    }
    // In case of mbim there are no appended status bytes in the APDU received.
    // Hence no extra bytes to be removed.
    modem_mbim->responses_.push_back(payload.ReleaseOnly());
    std::move(modem_mbim->tx_queue_[0].cb_).Run(lpa::card::EuiccCard::kNoError);
    modem_mbim->tx_queue_.pop_front();
    modem_mbim->TransmitFromQueue();
  } else {
    std::move(modem_mbim->tx_queue_[0].cb_)
        .Run(lpa::card::EuiccCard::kSendApduError);
    modem_mbim->tx_queue_.pop_front();
    modem_mbim->TransmitFromQueue();
    return;
  }
}

/* static */
void ModemMbim::ClientIndicationCb(MbimDevice* device,
                                   MbimMessage* notification,
                                   ModemMbim* modem_mbim) {
  MbimService service;
  g_autoptr(GError) error = NULL;
  service = mbim_message_indicate_status_get_service(notification);

  VLOG(2) << "Received notification for service: "
          << mbim_service_get_string(service);
  VLOG(2) << "Command received from the modem: "
          << mbim_cid_get_printable(
                 service, mbim_message_indicate_status_get_cid(notification));

  switch (service) {
    case MBIM_SERVICE_BASIC_CONNECT:
      if (mbim_message_indicate_status_get_cid(notification) ==
          MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS) {
        MbimSubscriberReadyState ready_state;
        if (mbim_message_subscriber_ready_status_notification_parse(
                notification, &ready_state,
                /* subscriber_id */ NULL,
                /* sim_iccid */ NULL,
                /* ready_info */ NULL,
                /* telephone_numbers_count */ NULL,
                /* telephone_numbers */ NULL, &error)) {
          modem_mbim->ready_state_ = ready_state;
          modem_mbim->is_ready_state_valid = true;
          LOG(INFO) << "Current sim status: " << ready_state;
          if (ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED) {
            VLOG(2) << "Sim has one profile enabled";
          } else if (ready_state ==
                     MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED) {
            VLOG(2) << "Sim not inserted";
          }
        }
      }
      break;
    default:
      VLOG(2) << "Indication received is not handled";
      break;
  }
  return;
}

bool ModemMbim::State::Transition(ModemMbim::State::Value value) {
  bool valid_transition = true;
  switch (value) {
    case kMbimUninitialized:
      valid_transition = true;
      break;
    default:
      // Most states can only transition from the previous state.
      valid_transition = (value == value_ + 1);
  }
  if (valid_transition) {
    LOG(INFO) << "Transitioning from state " << *this << " to state "
              << State(value);
    value_ = value;
  } else {
    LOG(ERROR) << "Cannot transition from state " << *this << " to state "
               << State(value);
  }
  return valid_transition;
}

void ModemMbim::StoreAndSetActiveSlot(const uint32_t physical_slot,
                                      ResultCallback cb) {
  // Get the slot from libmbim
  LOG(INFO) << __func__ << " physical_slot:" << physical_slot;
  auto reacquire_channel = base::BindOnce(
      &ModemMbim::ReacquireChannel, weak_factory_.GetWeakPtr(), physical_slot);
  // The modem may be reset, causing device_ to be invalid. Retry init to be
  // safe.
  RetryInitialization(base::BindOnce(&RunNextStep, std::move(reacquire_channel),
                                     std::move(cb)));
}

void ModemMbim::StartProfileOp(uint32_t physical_slot, ResultCallback cb) {
  LOG(INFO) << __func__ << " physical_slot:" << physical_slot;
  retry_count_ = 0;
  is_ready_state_valid = false;
  StoreAndSetActiveSlot(physical_slot, std::move(cb));
}

void ModemMbim::FinishProfileOp(ResultCallback cb) {
  LOG(INFO) << __func__;
  const guint MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE = 7;
  if (!is_ready_state_valid ||
      !(ready_state_ == MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED ||
        ready_state_ == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED ||
        ready_state_ == MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE)) {
    if (retry_count_ > kMaxRetries) {
      LOG(ERROR) << "Could not finish profile operation, ready_state_="
                 << ready_state_
                 << ", is_ready_state_valid=" << is_ready_state_valid;
      std::move(cb).Run(kModemMessageProcessingError);
      return;
    }
    retry_count_++;
    executor_->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&ModemMbim::FinishProfileOp, weak_factory_.GetWeakPtr(),
                       std::move(cb)),
        kSimRefreshDelay);
    return;
  }
  retry_count_ = 0;
  AcquireChannel(std::move(cb));
}

void ModemMbim::RestoreActiveSlot(ResultCallback cb) {
  LOG(INFO) << __func__ << "++";
  std::move(cb).Run(kModemSuccess);
}

bool ModemMbim::IsSimValidAfterEnable() {
  VLOG(2) << __func__ << "++";
  return false;
  // The sim issues a proactive refresh after an enable. This
  // function should return true immediately after the refresh completes,
  // However, the LPA expects that this function does not read any
  // other state variable. Thus, we simply return false until the LPA
  // times out, and then finish the operation. This imposes a 15 sec penalty
  // on every enable and 30 sec penalty on every disable.
  // A workaround is to return true and complete the eSIM operation before the
  // refresh. FinishProfileOp can gate the dbus response until the refresh is
  // complete. However, this exposes UI issues.
}

bool ModemMbim::IsSimValidAfterDisable() {
  VLOG(2) << __func__ << "++";
  return false;
}

}  // namespace hermes
