// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include <assert.h>
#include <fstream>
#include <getopt.h>
#include <iterator>
#include <memory>
#include <sstream>
#include <string>

#include "sw/host/spiflash/ftdi_spi_interface.h"
#include "sw/host/spiflash/spi_interface.h"
#include "sw/host/spiflash/updater.h"
#include "sw/host/spiflash/verilator_spi_interface.h"

namespace {

using opentitan::spiflash::Frame;
using opentitan::spiflash::FtdiSpiInterface;
using opentitan::spiflash::SpiInterface;
using opentitan::spiflash::Updater;
using opentitan::spiflash::VerilatorSpiInterface;

constexpr char kUsageString[] = R"R( usage options:
  --input=Input image in binary format.

FTDI Options:
  [--dev-id="vid:pid"] FTDI device ID.
    vid: Vendor ID in string hex format.
    pid: Product ID in string hex format.
  [--dev-sn=string] FTDI serial number. Requires --dev-id to be set.

Verilator Options:
  [--verilator=filehandle] Enables Verilator mode with SPI filehandle.
  [--process-delay=microseconds] Frame transmission delay for frame processing.

Protocol Options:
  [--erase-delay=microseconds] Frame transmission delay for flash erase.

DV Options:
  [--dump-frames=filehandle] Dump binary SPI flash frames in binary format.
)R";

/** SPI flash list of supported command actions. */
enum class SpiFlashAction {
  /** Invalid command action. */
  kInvalid = 0,

  /** Run SPI flash in FTDI mode. */
  kFtdi,

  /** Run SPI flash in Verilator mode. */
  kVerilator,

  /** Covert input binrary into frames. */
  kDumpFrames,

  /** Print usage information/help. */
  kPrintUsage,
};

/** SPI flash configuration options. */
struct SpiFlashOpts {
  /** Input file in binary format. */
  std::string input;

  /** Output filename to dump SPI frames */
  std::string output_filename;

  /** Set to SPI flash  mode of operation */
  SpiFlashAction action = SpiFlashAction::kInvalid;

  /** FTDI configuration options. */
  FtdiSpiInterface::Options ftdi_options;

  /** Verilator configuration options. */
  VerilatorSpiInterface::Options verilator_options;

  /** Time to wait for flash to erase on transmission of first frame. */
  int32_t flash_erase_delay_us = 100000;
};

/**
 * Get `filename` contents and store them in `contents`. Using std::string for
 * `filename` because underlying open file call requires a C string.
 */
bool GetFileContents(const std::string &filename, std::string *contents) {
  assert(contents);
  std::ifstream file_stream(filename, std::ios::in | std::ios::binary);
  if (!file_stream) {
    std::cerr << "Unable to open: " << filename << " errno: " << errno
              << std::endl;
    return false;
  }
  std::ostringstream in_stream;
  in_stream << file_stream.rdbuf();
  file_stream.close();
  *contents = in_stream.str();
  return true;
}

/**
 * Store the contetns of `code` formatted int SPI flash frame binary format
 * into `output_filename`
 */
bool DumpFramesToFile(const std::string &code,
                      const std::string &output_filename) {
  std::vector<Frame> frames;
  if (!Updater::GenerateFrames(code, &frames)) {
    return false;
  }
  std::ofstream out_stream;
  out_stream.open(output_filename, std::ofstream::out | std::ofstream::binary);
  if (!out_stream.good()) {
    std::cerr << "Unable to open file: " << output_filename << std::endl;
    return false;
  }
  for (const Frame &f : frames) {
    out_stream.write(reinterpret_cast<const char *>(&f), sizeof(Frame));
    if (!out_stream.good()) {
      std::cerr << "Detected write error. Output file may be corrupted."
                << std::endl;
      out_stream.close();
      return false;
    }
  }
  out_stream.close();
  return true;
}

/** Print help menu. */
static void PrintUsage(int argc, char *argv[]) {
  assert(argc >= 1);
  std::cerr << argv[0] << kUsageString << std::endl;
}

/*
 * Extract the vendor and product ID from `device_id` and store the values
 * in `options`.
 *
 * This function may throw exceptions.
 *
 * @return true on success.
 */
bool ParseDeviceID(const std::string &device_id, SpiFlashOpts *options) {
  size_t token_pos = device_id.find(':');
  if (token_pos == std::string::npos) {
    std::cerr << "Unable to find device separator ':' in --device-id."
              << std::endl;
    return false;
  }

  std::string vendor_id = device_id.substr(/*pos=*/0, /*len=*/token_pos);
  options->ftdi_options.device_vendor_id =
      std::stoi(vendor_id, /*pos=*/0, /*base=*/16);

  std::string product_id =
      device_id.substr(/*pos=*/token_pos + 1, /*len=*/std::string::npos);
  options->ftdi_options.device_product_id =
      std::stoi(product_id, /*pos=*/0, /*base=*/16);

  return true;
}

/*
 * Parse command line arguments and store results in `options`.
 */
bool ParseArgs(int argc, char **argv, SpiFlashOpts *options) {
  assert(options);
  const struct option long_options[] = {
      {"input", required_argument, nullptr, 'i'},
      {"dev-id", required_argument, nullptr, 'd'},
      {"dev-sn", required_argument, nullptr, 'n'},
      {"dump-frames", required_argument, nullptr, 'x'},
      {"verilator", required_argument, nullptr, 's'},
      {"erase-delay", required_argument, nullptr, 'e'},
      {"process-delay", required_argument, nullptr, 'p'},
      {"help", no_argument, nullptr, 'h'},
      {nullptr, no_argument, nullptr, 0}};

  while (true) {
    int c = getopt_long(argc, argv, "i:d:e:n:p:s:x:h?", long_options, nullptr);
    if (c == -1) {
      // if only input file was given default to using FTDI
      if (!options->input.empty() &&
          options->action == SpiFlashAction::kInvalid) {
        options->action = SpiFlashAction::kFtdi;
      }
      return true;
    }

    switch (c) {
      case 0:
        break;
      case 'i':
        options->input = optarg;
        break;
      case 'd':
        if (!ParseDeviceID(std::string(optarg), options)) {
          return false;
        }
        break;
      case 'e':
        options->flash_erase_delay_us = std::stoi(optarg);
        break;
      case 'n':
        options->action = SpiFlashAction::kFtdi;
        options->ftdi_options.device_serial_number = optarg;
        break;
      case 'p':
        options->verilator_options.frame_process_delay_us = std::stoi(optarg);
        break;
      case 's':
        options->action = SpiFlashAction::kVerilator;
        options->verilator_options.target = optarg;
        break;
      case 'x':
        options->action = SpiFlashAction::kDumpFrames;
        options->output_filename = optarg;
        break;
      case '?':
      case 'h':
        options->action = SpiFlashAction::kPrintUsage;
        break;
      default:;
    }
  }
  return true;
}

}  // namespace

int main(int argc, char **argv) {
  SpiFlashOpts spi_flash_options;
  if (!ParseArgs(argc, argv, &spi_flash_options)) {
    std::cerr << "Failed to parse command line options." << std::endl;
    return 1;
  }

  if (spi_flash_options.action == SpiFlashAction::kInvalid) {
    std::cerr << "Unable to detect valid command line arguments." << std::endl;
    PrintUsage(argc, argv);
    return 1;
  }

  if (spi_flash_options.action == SpiFlashAction::kPrintUsage) {
    PrintUsage(argc, argv);
    return 0;
  }

  std::string code;
  if (!GetFileContents(spi_flash_options.input, &code)) {
    return 1;
  }

  if (spi_flash_options.action == SpiFlashAction::kDumpFrames) {
    return DumpFramesToFile(code, spi_flash_options.output_filename) ? 0 : 1;
  }

  std::unique_ptr<SpiInterface> spi;
  if (spi_flash_options.action == SpiFlashAction::kVerilator) {
    spi = std::make_unique<VerilatorSpiInterface>(
        spi_flash_options.verilator_options);
  } else {
    spi = std::make_unique<FtdiSpiInterface>(spi_flash_options.ftdi_options);
  }
  if (!spi->Init()) {
    return 1;
  }

  Updater::Options options;
  options.code = code;
  options.flash_erase_delay_us = spi_flash_options.flash_erase_delay_us;

  Updater updater(options, std::move(spi));
  return updater.Run() ? 0 : 1;
}
