#include "host_exchange_plan.hpp"

#include <cstdint>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <string>

namespace {
std::uint32_t number(const char *text) {
  std::size_t consumed = 0;
  const auto value = std::stoull(text, &consumed, 0);
  if (text[consumed] != '\0' || value > UINT32_MAX)
    throw std::invalid_argument("invalid 32-bit number: " + std::string(text));
  return static_cast<std::uint32_t>(value);
}

void print(hostxcode::PacketHeader header) {
  std::cout << "0x" << std::hex << std::setfill('0') << std::setw(8)
            << header.word0 << " 0x" << std::setw(8) << header.word1 << '\n';
}
} // namespace

int main(int argc, char **argv) try {
  if (argc == 6 && std::string(argv[1]) == "h2d") {
    print(hostxcode::hostToTile(number(argv[2]), number(argv[3]),
                                number(argv[4]), number(argv[5])));
    return 0;
  }
  if (argc == 5 && std::string(argv[1]) == "d2h") {
    print(hostxcode::tileToHost(number(argv[2]), number(argv[3]),
                                number(argv[4])));
    return 0;
  }
  if (argc == 4 && std::string(argv[1]) == "close") {
    print(hostxcode::zeroByteRead(number(argv[2]), number(argv[3])));
    return 0;
  }
  std::cerr << "usage:\n"
               "  host_exchange_plan_dump h2d TILE TILE_ADDRESS HOST_OFFSET BYTES\n"
               "  host_exchange_plan_dump d2h TILE HOST_OFFSET BYTES\n"
               "  host_exchange_plan_dump close TILE DUMMY_TILE_ADDRESS\n";
  return 2;
} catch (const std::exception &error) {
  std::cerr << "host_exchange_plan_dump: " << error.what() << '\n';
  return 1;
}
