// 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 HERMES_MODEM_H_
#define HERMES_MODEM_H_

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

#include <google-lpa/lpa/card/euicc_card.h>

#include "hermes/apdu.h"
#include "hermes/euicc_interface.h"
#include "hermes/hermes_common.h"

namespace hermes {

constexpr int kMaxRetries = 5;
constexpr int kMaxApduLen = 260;
constexpr auto kSimRefreshDelay = base::TimeDelta::FromSeconds(3);
constexpr auto kInitRetryDelay = base::TimeDelta::FromSeconds(10);
constexpr int kModemSuccess = 0;
// This error will be returned when a received mbim/qmi message cannot be parsed
// or when it is received in an unexpected state.
constexpr int kModemMessageProcessingError = -1;
constexpr uint8_t kInvalidChannel = 0;

// Modem houses code shared by ModemQrtr and ModemMbim
// T is the type of message that the modem implementation uses. For
// QMI, messages are stored in objects of type QmiCmdInterface, and for MBIM,
// messages are stored in objects of type MbimCmd.
template <typename T>
class Modem : public EuiccInterface {
 public:
  Modem(Logger* logger, Executor* executor)
      : euicc_manager_(nullptr),
        logger_(logger),
        executor_(executor),
        retry_count_(0),
        current_transaction_id_(static_cast<uint16_t>(-1)),
        weak_factory_(this) {
    // Set SGP.22 specification version supported by this implementation (this
    // is not currently constrained by the eUICC we use).
    spec_version_.set_major(2);
    spec_version_.set_minor(2);
    spec_version_.set_revision(0);
  }

  virtual ~Modem() = default;

  // lpa::card::EuiccCard overrides.
  void SendApdus(std::vector<lpa::card::Apdu> apdus,
                 ResponseCallback cb) override;
  // IsSimValidAfter..able() is called by the lpa after profile enable/disable
  bool IsSimValidAfterEnable() override { return true; };
  bool IsSimValidAfterDisable() override { return true; };
  std::string GetImei() override { return imei_; };
  const lpa::proto::EuiccSpecVersion& GetCardVersion() override {
    return spec_version_;
  }
  lpa::util::EuiccLog* logger() override { return logger_; }
  lpa::util::Executor* executor() override { return executor_; }

 protected:
  // Base class for the tx info specific to a certain type of message to the
  // modem.
  // Uim command types that need any additional information should define
  // a child class. An instance of that class should be set to the data pointer
  // in its corresponding TxElement. For e.g. Apdu's require apdu info (thus, we
  // need an ApduTxInfo child class)
  struct TxInfo {
    virtual ~TxInfo() = default;
  };

  struct ApduTxInfo : public TxInfo {
    explicit ApduTxInfo(CommandApdu apdu) : apdu_(std::move(apdu)) {}
    CommandApdu apdu_;
  };

  struct TxElement {
    // TxInfo stores any parameters that msg_ takes
    std::unique_ptr<TxInfo> info_;
    uint16_t id_;
    // msg_ stores the type of msg to be sent. For e.g. if TxInfo contains
    // an apdu, then the msg_ should point to UimCmd::UimType::kSendApdu or
    // MbimType::kSendApdu.
    std::unique_ptr<T> msg_;
    // This cb_ maybe called once a response for the msg_ is received.
    // The callback must accept an int which is the return value of the qmi
    // operation
    base::OnceCallback<void(int)> cb_;
  };

  uint16_t AllocateId();
  // The tag is used by TransmitFromQueue to distinguish apdu's from other types
  // of messages in the tx_queue.
  virtual std::unique_ptr<T> GetTagForSendApdu() = 0;
  // Convenience function that runs the lpa callback if err==0
  virtual void SendApdusResponse(ResponseCallback callback, int err);
  // SendApdus will queue APDU's on tx_queue_ and call TransmitFromQueue()
  // In the QMI and MBIM implementations, TransmitFromQueue also processes
  // other messages like reset, close channel, open channel etc.
  virtual void TransmitFromQueue() = 0;
  virtual void Shutdown() = 0;
  void RetryInitialization(ResultCallback cb);
  void RunNextStepOrRetry(
      base::OnceCallback<void(base::OnceCallback<void(int)>)> next_step,
      base::OnceCallback<void(int)> cb,
      int err);
  // List of responses for the oldest SendApdus call that hasn't been completely
  // processed.
  std::vector<std::vector<uint8_t>> responses_;
  std::deque<TxElement> tx_queue_;

  // Used to send notifications about eSIM slot changes.
  EuiccManagerInterface* euicc_manager_;

  Logger* logger_;
  Executor* executor_;
  lpa::proto::EuiccSpecVersion spec_version_;
  std::string imei_;
  int retry_count_;
  base::OnceClosure retry_initialization_callback_;

 private:
  uint16_t current_transaction_id_;
  base::WeakPtrFactory<Modem<T>> weak_factory_;
};

template <typename T>
void Modem<T>::SendApdus(std::vector<lpa::card::Apdu> apdus,
                         ResponseCallback cb) {
  base::OnceCallback<void(int)> callback;
  callback = base::BindOnce(&Modem<T>::SendApdusResponse,
                            weak_factory_.GetWeakPtr(), std::move(cb));
  LOG(INFO) << __func__;
  for (size_t i = 0; i < apdus.size(); ++i) {
    CommandApdu apdu(static_cast<ApduClass>(apdus[i].cla()),
                     static_cast<ApduInstruction>(apdus[i].ins()),
                     /* is_extended_length */ false);
    apdu.AddData(apdus[i].data());
    tx_queue_.push_back({std::make_unique<ApduTxInfo>(std::move(apdu)),
                         AllocateId(), GetTagForSendApdu(),
                         i == apdus.size() - 1
                             ? std::move(callback)
                             : base::BindOnce(&PrintMsgProcessingResult)});
  }
  TransmitFromQueue();
}

template <typename T>
void Modem<T>::SendApdusResponse(EuiccInterface::ResponseCallback callback,
                                 int err) {
  callback(responses_, err);
  // ResponseCallback interface does not indicate a change in ownership of
  // |responses_|, but all callbacks should transfer ownership.
  CHECK(responses_.empty());
}

template <typename T>
uint16_t Modem<T>::AllocateId() {
  // transaction id cannot be 0 for QMI, but when incrementing by 1, an overflow
  // will result in this method at some point returning 0. Incrementing by 2
  // when transaction_id is initialized as an odd number guarantees us that this
  // method will never return 0 without special-casing the overflow.
  DCHECK_NE(current_transaction_id_, 0);
  current_transaction_id_ += 2;
  return current_transaction_id_;
}

template <typename T>
void Modem<T>::RetryInitialization(ResultCallback cb) {
  if (retry_count_ > kMaxRetries) {
    LOG(INFO) << __func__ << ": Max retry count(" << kMaxRetries
              << ") exceeded, will not retry initialization.";
    retry_count_ = 0;
    while (!tx_queue_.empty()) {
      std::move(tx_queue_[0].cb_).Run(kModemMessageProcessingError);
      tx_queue_.pop_front();
    }
    std::move(cb).Run(kModemMessageProcessingError);
    return;
  }
  LOG(INFO) << "Reprobing for eSIM in " << kInitRetryDelay.InSeconds()
            << " seconds";
  Shutdown();
  retry_initialization_callback_.Reset();
  retry_initialization_callback_ =
      base::BindOnce(&Modem<T>::Initialize, weak_factory_.GetWeakPtr(),
                     euicc_manager_, std::move(cb));
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, std::move(retry_initialization_callback_), kInitRetryDelay);
  retry_count_++;
}

template <typename T>
void Modem<T>::RunNextStepOrRetry(
    base::OnceCallback<void(base::OnceCallback<void(int)>)> next_step,
    base::OnceCallback<void(int)> cb,
    int err) {
  if (err) {
    RetryInitialization(std::move(cb));
    return;
  }
  RunNextStep(std::move(next_step), std::move(cb), err);
}

}  // namespace hermes

#endif  // HERMES_MODEM_H_
