#include <cmath>
#include <cstring>
#include <list>

#include "firmware.hpp"
#include "quadspi.h"
#include "CDCCommandStream.h"
#include "usbd_cdc_if.h"
#include "file.hpp"
#include "executable.hpp"
#include "dialog.hpp"
#include "engine/api_private.hpp"

using namespace blit;

constexpr uint32_t qspi_flash_sector_size = 64 * 1024;
constexpr uint32_t qspi_flash_size = 32768 * 1024;
constexpr uint32_t qspi_flash_address = 0x90000000;

// resevered space for temp/cached files
constexpr uint32_t qspi_tmp_reserved = 4 * 1024 * 1024;

extern CDCCommandStream g_commandStream;

FlashLoader flashLoader;
CDCEraseHandler cdc_erase_handler;
CDCLaunchHandler cdc_launch_handler;

struct GameInfo {
  char title[25], author[17];
  char category[17];
  uint32_t size = 0, checksum = 0;

  uint32_t offset = ~0;
};

struct HandlerInfo {
  uint32_t offset, meta_offset;
  char type[5];
};

std::list<GameInfo> game_list;

std::list<HandlerInfo> handlers; // flashed games that can "launch" files

std::list<std::tuple<uint16_t, uint16_t>> free_space; // block start, count

uint32_t launcher_offset = ~0;
bool flash_scanned = false;

Dialog dialog;

bool cached_file_in_tmp = false;

// metadata

static bool parse_flash_metadata(uint32_t offset, GameInfo &info) {
  auto meta_offset = offset + info.size;
  auto game_offset = offset;

  uint8_t buf[10];
  if(qspi_read_buffer(meta_offset, buf, 10) != QSPI_OK)
    return false;

  if(memcmp(buf, "BLITMETA", 8) != 0)
    return false;

  RawMetadata raw_meta;
  if(qspi_read_buffer(meta_offset + 10, reinterpret_cast<uint8_t *>(&raw_meta), sizeof(RawMetadata)) != QSPI_OK) {
    return false;
  }

  info.size += *reinterpret_cast<uint16_t *>(buf + 8) + 10;
  info.checksum = raw_meta.crc32;
  memcpy(info.title, raw_meta.title, sizeof(info.title));
  memcpy(info.author, raw_meta.author, sizeof(info.author));

  offset = meta_offset + sizeof(RawMetadata) + 10;

  if(qspi_read_buffer(offset, buf, 8) != QSPI_OK)
    return true;

  if(memcmp(buf, "BLITTYPE", 8) != 0) {
    memcpy(info.category, "none", 5);
    return true;
  }

  // type chunk
  RawTypeMetadata type_meta;
  if(qspi_read_buffer(offset + 8, reinterpret_cast<uint8_t *>(&type_meta), sizeof(RawTypeMetadata)) != QSPI_OK)
    return false;

  memcpy(info.category, type_meta.category, sizeof(info.category));

  offset += 8 + sizeof(RawTypeMetadata);

  // register handler
  HandlerInfo handler;
  handler.offset = game_offset;
  handler.meta_offset = meta_offset;
  handler.type[4] = 0;

  for(int i = 0; i < type_meta.num_filetypes; i++) {
    qspi_read_buffer(offset, (uint8_t *)handler.type, 5);
    offset += 5;
    handlers.push_back(handler);
  }

  return true;
}

static bool parse_file_metadata(FIL &fh, GameInfo &info) {
  BlitGameHeader header;
  UINT bytes_read;
  bool result = false;
  f_lseek(&fh, 0);
  f_read(&fh, &header, sizeof(header), &bytes_read);

  // skip relocation data
  int off = 0;
  if(header.magic == 0x4F4C4552 /* RELO */) {
    f_lseek(&fh, 4);
    uint32_t num_relocs;
    f_read(&fh, (void *)&num_relocs, 4, &bytes_read);

    off = num_relocs * 4 + 8;
    f_lseek(&fh, off);

    // re-read header
    f_read(&fh, &header, sizeof(header), &bytes_read);
  }

  if(header.magic == blit_game_magic) {
    uint8_t buf[10];
    f_lseek(&fh, (header.end - qspi_flash_address) + off);
    f_read(&fh, buf, 10, &bytes_read);

    if(bytes_read == 10 && memcmp(buf, "BLITMETA", 8) == 0) {
      // don't bother reading the whole thing since we don't want the images
      RawMetadata raw_meta;
      f_read(&fh, &raw_meta, sizeof(RawMetadata), &bytes_read);

      info.size += *reinterpret_cast<uint16_t *>(buf + 8) + 10;
      info.checksum = raw_meta.crc32;
      memcpy(info.title, raw_meta.title, sizeof(info.title));
      memcpy(info.author, raw_meta.author, sizeof(info.author));

      result = true;
    }

    // read category
    f_read(&fh, buf, 8, &bytes_read);
    if(bytes_read == 8 && memcmp(buf, "BLITTYPE", 8) == 0) {
      RawTypeMetadata type_meta;
      f_read(&fh, &type_meta, sizeof(RawTypeMetadata), &bytes_read);
      memcpy(info.category, type_meta.category, sizeof(info.category));
    }

  }

  return result;
}

static int calc_num_blocks(uint32_t size) {
  return (size - 1) / qspi_flash_sector_size + 1;
}

static void erase_qspi_flash(uint32_t start_offset, uint32_t size_bytes) {
  uint32_t sector_count = calc_num_blocks(size_bytes);

  progress.show("Erasing flash sectors...", sector_count);

  for(uint32_t sector = 0; sector < sector_count; sector++) {
    qspi_sector_erase(start_offset + sector * qspi_flash_sector_size);

    progress.update(sector);
  }

  progress.hide();
}

// returns true is there is a valid header here
static bool read_flash_game_header(uint32_t offset, BlitGameHeader &header) {
  if(qspi_read_buffer(offset, reinterpret_cast<uint8_t *>(&header), sizeof(header)) != QSPI_OK)
    return false;

  if(header.magic != blit_game_magic)
    return false;

  // make sure end/size is sensible
  if(header.end <= qspi_flash_address)
    return false;

  return true;
}

static void scan_flash() {
  game_list.clear();
  free_space.clear();
  handlers.clear();

  GameInfo game;
  uint32_t free_start = 0xFFFFFFFF;

  for(uint32_t offset = 0; offset < qspi_flash_size - qspi_tmp_reserved;) {
    BlitGameHeader header;

    if(!read_flash_game_header(offset, header)) {
      if(free_start == 0xFFFFFFFF)
        free_start = offset;

      offset += qspi_flash_sector_size;
      continue;
    }

    game.offset = offset;
    game.size = header.end - qspi_flash_address;

    // check for valid metadata
    if(parse_flash_metadata(offset, game)) {
      // find the launcher
      if(strcmp(game.category, "launcher") == 0)
        launcher_offset = offset;

      // remove old firmware updates
      if(strcmp(game.category, "firmware") == 0 && persist.reset_target == prtFirmware) {
        int size_blocks = calc_num_blocks(game.size);

        erase_qspi_flash(offset, size_blocks * qspi_flash_sector_size);
        offset += size_blocks * qspi_flash_sector_size;
        continue;
      }
    }

    game_list.push_back(game);

    // add free space to list
    if(free_start != 0xFFFFFFFF) {
      auto start_block = free_start / qspi_flash_sector_size;
      auto end_block = offset / qspi_flash_sector_size;

      free_space.emplace_back(start_block, end_block - start_block);

      free_start = 0xFFFFFFFF;
    }

    offset += calc_num_blocks(game.size) * qspi_flash_sector_size;
  }

  // final free
  if(free_start != 0xFFFFFFFF) {
    auto start_block = free_start / qspi_flash_sector_size;
    auto end_block = (qspi_flash_size - qspi_tmp_reserved) / qspi_flash_sector_size;

    free_space.emplace_back(start_block, end_block - start_block);
  }
}

static bool cleanup_duplicates(GameInfo &new_game, uint32_t new_game_offset) {
  bool is_launcher = strcmp(new_game.category, "launcher") == 0;

  bool ret = false;

  for(auto &game : game_list) {
    if(game.offset == new_game_offset)
      continue;

    bool erased = false;

    if(strcmp(game.title, new_game.title) == 0 && strcmp(game.author, new_game.author) == 0) {
      erase_qspi_flash(game.offset, game.size);
      erased = true;
    } else if(is_launcher && strcmp(game.category, "launcher") == 0) {
      // flashing a launcher, remove previous launchers
      erase_qspi_flash(game.offset, game.size);
      erased = true;
    }

    // we just erased the thing that was running
    if(erased && game.offset == persist.last_game_offset)
      ret = true;
  }

  return ret;
}

// returns address to flash file to
static uint32_t get_flash_offset_for_file(uint32_t file_size) {

  int file_blocks = calc_num_blocks(file_size);

  for(auto space : free_space) {
    if(std::get<1>(space) >= file_blocks)
      return std::get<0>(space) * qspi_flash_sector_size;
  }

  // TODO: handle flash full
  return 0;
}

static bool flash_buffer(uint32_t offset, uint8_t *buffer, size_t size) {
  uint8_t verify_buffer[SD_BUFFER_SIZE];

  if(qspi_write_buffer(offset, buffer, size) != QSPI_OK)
    return false;

  if(qspi_read_buffer(offset, verify_buffer, size) != QSPI_OK)
    return false;

  // compare buffers
  bool verified = true;
  for(size_t i = 0; i < size && verified; i++)
    verified = buffer[i] == verify_buffer[i];

  return verified;
}

// apply relocations to a chunk of a file
static void apply_relocs(uint32_t file_offset, uint32_t flash_base_offset, uint8_t *buffer, size_t buf_len, const std::vector<uint32_t> &relocation_offsets, size_t &cur_reloc) {
  if(cur_reloc >= relocation_offsets.size())
    return;

  for(auto off = file_offset; off < file_offset + buf_len; off += 4) {
    if(off == relocation_offsets[cur_reloc]) {
      *(uint32_t *)(buffer + off - file_offset) += flash_base_offset;
      cur_reloc++;
    }
  }
}

// Flash a file from the SDCard to external flash
static uint32_t flash_from_sd_to_qspi_flash(FIL &file, uint32_t flash_offset) {
  FRESULT res;

  // get file length
  FSIZE_t bytes_total = f_size(&file);
  UINT bytes_read = 0;
  FSIZE_t bytes_flashed = 0;

  // check for prepended relocation info
  char buf[4];
  f_lseek(&file, 0);
  f_read(&file, buf, 4, &bytes_read);
  std::vector<uint32_t> relocation_offsets;
  size_t cur_reloc = 0;
  bool has_relocs = false;

  if(memcmp(buf, "RELO", 4) == 0) {
    uint32_t num_relocs;
    f_read(&file, (void *)&num_relocs, 4, &bytes_read);
    relocation_offsets.reserve(num_relocs);

    for(auto i = 0u; i < num_relocs; i++) {
      uint32_t reloc_offset;
      f_read(&file, (void *)&reloc_offset, 4, &bytes_read);

      relocation_offsets.push_back(reloc_offset - qspi_flash_address);
    }

    bytes_total -= num_relocs * 4 + 8; // size of relocation data
    has_relocs = true;
  } else {
    f_lseek(&file, 0);
  }

  if(!has_relocs)
    flash_offset = 0;
  else if(flash_offset == 0xFFFFFFFF)
    flash_offset = get_flash_offset_for_file(bytes_total);

  // erase the sectors needed to write the image
  erase_qspi_flash(flash_offset, bytes_total);

  progress.show("Copying from SD card to flash...", bytes_total);

  const int buffer_size = SD_BUFFER_SIZE;
  uint8_t buffer[buffer_size];

  while(bytes_flashed < bytes_total) {
    // limited ram so a bit at a time
    res = f_read(&file, (void *)buffer, buffer_size, &bytes_read);

    if(res != FR_OK)
      break;

    // relocation patching
    apply_relocs(bytes_flashed, flash_offset, buffer, bytes_read, relocation_offsets, cur_reloc);

    if(!flash_buffer(bytes_flashed + flash_offset, buffer, bytes_read))
      break;

    bytes_flashed += bytes_read;

    progress.update(bytes_flashed);
  }

  progress.hide();

  // update free space
  for(auto &space : free_space) {
    if(std::get<0>(space) == flash_offset / qspi_flash_sector_size) {
      auto size = calc_num_blocks(bytes_total);
      std::get<0>(space) += size;
      std::get<1>(space) -= size;
    }
  }

  return bytes_flashed == bytes_total ? flash_offset : 0xFFFFFFFF;
}

// runs a .blit file, flashing it if required
static bool launch_game_from_sd(const char *path, bool auto_delete = false) {
  if(is_qspi_memorymapped()) {
    qspi_disable_memorymapped_mode();
    blit_disable_user_code(); // assume user running
  }

  uint32_t launch_offset = 0xFFFFFFFF;
  uint32_t flash_offset = launch_offset;

  FIL file;
  FRESULT res = f_open(&file, path, FA_READ);
  if(res != FR_OK)
    return false;

  // get size
  // this is a little duplicated...
  FSIZE_t bytes_total = f_size(&file);
  char buf[8];
  UINT read;
  f_read(&file, buf, 8, &read);
  if(memcmp(buf, "RELO", 4) == 0) {
    auto num_relocs = *(uint32_t *)(buf + 4);
    bytes_total -= num_relocs * 4 + 8;
  }

  GameInfo meta;
  if(parse_file_metadata(file, meta)) {

    for(auto &flash_game : game_list) {
      // if a game with the same name/crc is already installed, launch that one instead of flashing it again
      if(flash_game.checksum == meta.checksum && strcmp(flash_game.title, meta.title) == 0) {
        launch_offset = flash_game.offset;
        break;
      } else if(strcmp(flash_game.title, meta.title) == 0 && strcmp(flash_game.author, meta.author) == 0) {
        // same game, different version
        if(calc_num_blocks(flash_game.size) >= calc_num_blocks(bytes_total)) {
          flash_offset = flash_game.offset;
          break;
        }
      }
    }

    // cleanup any other duplicates if we're going to flash
    if(launch_offset == 0xFFFFFFFF)
      cleanup_duplicates(meta, launch_offset);
  }

  if(launch_offset == 0xFFFFFFFF)
    launch_offset = flash_from_sd_to_qspi_flash(file, flash_offset);

  f_close(&file);

  if(launch_offset != 0xFFFFFFFF) {
    if(auto_delete)
      ::remove_file(path);

    return blit_switch_execution(launch_offset, true);
  }

  blit_enable_user_code();

  return false;
}

// launches a file using the approprite handler
static bool launch_file_from_sd(const char *path) {
  persist.launch_path[0] = 0;

  if(strncmp(path, "flash:/", 7) == 0) {
    return blit_switch_execution(atoi(path + 7) * qspi_flash_sector_size, true);
  }

  uint32_t launch_offset = 0xFFFFFFFF;

  // get the extension (assume there is one)
  std::string_view sv(path);
  auto ext = std::string(sv.substr(sv.find_last_of('.') + 1));
  for(auto &c : ext)
    c = tolower(c);

  if(ext != "blit") {
    // find the handler
    for(auto &handler : handlers) {
      if(handler.type == ext) {
        launch_offset = handler.offset;
        break;
      }
    }

    if(launch_offset == 0xFFFFFFFF)
      return false;

    // set the path to the file to launch
    strncpy(persist.launch_path, path, sizeof(persist.launch_path));

    return blit_switch_execution(launch_offset, true);
  }

  // .blit file, install/launch
  if(launch_game_from_sd(path))
    return true;

  return false;
}

static void erase_flash_game(uint32_t offset) {
  // reject unaligned
  if(offset & (qspi_flash_sector_size - 1))
    return;

  // attempt to get size, falling back to a single sector
  int erase_size = 1;
  for(auto &game : game_list) {
    if(game.offset == offset) {
      erase_size = calc_num_blocks(game.size);
      break;
    }
  }

  bool flash_mapped = is_qspi_memorymapped();
  if(flash_mapped) {
    blit_disable_user_code();
    qspi_disable_memorymapped_mode();
  }

  erase_qspi_flash(offset, erase_size * qspi_flash_sector_size);

  // rescan
  scan_flash();

  if(flash_mapped) {
    qspi_enable_memorymapped_mode();
    blit_enable_user_code();
  }
}

static void *get_type_handler_metadata(const char *filetype) {
  for(auto &handler : handlers) {
    if(strncmp(filetype, handler.type, 4) == 0)
      return (void *)(qspi_flash_address + handler.meta_offset);
  }

  return nullptr;
}

static const uint8_t *flash_to_tmp(const std::string &filename, uint32_t &size) {
  // one file at a time
  // TODO: this could be improved
  if(cached_file_in_tmp)
    return nullptr;

  FIL f;
  if(f_open(&f, filename.c_str(), FA_READ) != FR_OK)
    return nullptr;

  size = f_size(&f);

  if(f_size(&f) > qspi_tmp_reserved) {
    f_close(&f);
    return nullptr;
  }

  // only called through the API, game will be running
  blit_disable_user_code();
  qspi_disable_memorymapped_mode();

  auto flash_offset = qspi_flash_size - qspi_tmp_reserved;

  erase_qspi_flash(flash_offset, size);

  progress.show("Copying file to cache...", size);

  const int buffer_size = SD_BUFFER_SIZE;
  uint8_t buffer[buffer_size];

  FSIZE_t bytes_flashed = 0;
  while(bytes_flashed < size) {
    UINT bytes_read;
    auto res = f_read(&f, (void *)buffer, buffer_size, &bytes_read);

    if(res != FR_OK)
      break;

    if(!flash_buffer(bytes_flashed + flash_offset, buffer, bytes_read))
      break;

    bytes_flashed += bytes_read;

    progress.update(bytes_flashed);
  }

  progress.hide();

  qspi_enable_memorymapped_mode();
  blit_enable_user_code();

  f_close(&f);

  if(bytes_flashed < size)
    return nullptr;

  return (const uint8_t *)(qspi_flash_address + flash_offset);
}

static bool blit_is_launcher_running() {
  return launcher_offset == persist.last_game_offset;
}

static void tmp_file_closed(const uint8_t *ptr) {
  cached_file_in_tmp = false;
}

static void start_launcher() {
  if(launcher_offset == 0xFFFFFFFF)
    return;

  // if the launcher fails to start it's incompatible, ignore it
  if(!blit_switch_execution(launcher_offset, false))
    launcher_offset = 0xFFFFFFFF;
}

void init() {
  api.launch = launch_file_from_sd;
  api.erase_game = erase_flash_game;
  api.get_type_handler_metadata = get_type_handler_metadata;

  api.flash_to_tmp = flash_to_tmp;
  api.tmp_file_closed = tmp_file_closed;

  scan_flash();
  flash_scanned = true;

  set_screen_mode(ScreenMode::hires);

  // register PROG
  g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'P', 'R', 'O', 'G'>::value, &flashLoader);

  // register SAVE
  g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'S', 'A', 'V', 'E'>::value, &flashLoader);

  // register LS
  g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'_', '_', 'L', 'S'>::value, &flashLoader);

  g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'E', 'R', 'S', 'E'>::value, &cdc_erase_handler);

  g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'L', 'N', 'C', 'H'>::value, &cdc_launch_handler);

  // check for updates
  if(::file_exists("firmware-update.blit")) {
    // TODO: -vx.x.x?
    if(launch_game_from_sd("firmware-update.blit", true))
      return;
  }

  // then launcher updates
  if(::file_exists("launcher.blit")) {
    if(launch_game_from_sd("launcher.blit", true))
      return;
  }

  // auto-launch
  if(persist.reset_target == prtGame) {
    if(!blit_switch_execution(persist.last_game_offset, false)) {
      // failed to start, notify user and switch to launcher
      dialog.show("Oops!", "Failed to launch game!", [](bool yes) {
        start_launcher();
      }, false);
    }
  // error reset handling
  } else if(persist.reset_error) {
    dialog.show("Oops!", "Restart game?", [](bool yes){

      if(yes)
        blit_switch_execution(persist.last_game_offset, false);
      else
        start_launcher();

      persist.reset_error = false;
    });
  } else
    start_launcher();
}

void render(uint32_t time) {

  if(flash_scanned && launcher_offset == 0xFFFFFFFF) {
    screen.pen = Pen(0, 0, 0);
    screen.clear();

    screen.pen = Pen(255, 255, 255);
    screen.text(
      "Please flash a launcher!\n\nUse \"32blit flash launcher.blit\"\nor place launcher.blit on your SD card.",
      minimal_font, Point(screen.bounds.w / 2, screen.bounds.h / 2), true, TextAlign::center_center
    );
  }

  progress.draw();
  dialog.draw();
}

void update(uint32_t time) {
  if(dialog.update())
    return;

  // no game or launcher running, fix this
  if(launcher_offset != 0xFFFFFFFF && !blit_user_code_running())
    start_launcher();
}

// below here are the CDC handlers

static void cdc_flash_list() {
  bool mapped = is_qspi_memorymapped();

  if(mapped)
    qspi_disable_memorymapped_mode();

  // scan through flash and send offset, size and metadata
  for(uint32_t offset = 0; offset < qspi_flash_size;) {
    BlitGameHeader header;

    if(!read_flash_game_header(offset, header)) {
      offset += qspi_flash_sector_size;
      continue;
    }

    uint32_t size = header.end - qspi_flash_address;

    // metadata header
    uint8_t buf[10];
    if(qspi_read_buffer(offset + size, buf, 10) != QSPI_OK)
      break;

    while(CDC_Transmit_HS((uint8_t *)&offset, 4) == USBD_BUSY){}
    while(CDC_Transmit_HS((uint8_t *)&size, 4) == USBD_BUSY){}

    uint16_t metadata_len = 0;

    if(memcmp(buf, "BLITMETA", 8) == 0)
      metadata_len = *reinterpret_cast<uint16_t *>(buf + 8);

    while(CDC_Transmit_HS((uint8_t *)"BLITMETA", 8) == USBD_BUSY){}
    while(CDC_Transmit_HS((uint8_t *)&metadata_len, 2) == USBD_BUSY){}

    // send metadata
    uint32_t metadata_offset = offset + size + 10;
    while(metadata_len) {
      int chunk_size = std::min(256, (int)metadata_len);
      uint8_t metadata_buf[256];

      if(qspi_read_buffer(metadata_offset, metadata_buf, chunk_size) != QSPI_OK)
        break;

      while(CDC_Transmit_HS(metadata_buf, chunk_size) == USBD_BUSY){}

      metadata_offset += chunk_size;
      metadata_len -= chunk_size;
    }

    offset += calc_num_blocks(size) * qspi_flash_sector_size;
  }

  // end marker
  uint32_t end = 0xFFFFFFFF;
  while(CDC_Transmit_HS((uint8_t *)&end, 4) == USBD_BUSY){}

  if(mapped)
    qspi_enable_memorymapped_mode();
}

// erase command handler
CDCCommandHandler::StreamResult CDCEraseHandler::StreamData(CDCDataStream &dataStream) {
  uint32_t offset;
  if(!dataStream.Get(offset))
    return srNeedData;

  erase_flash_game(offset);

  return srFinish;
}

CDCCommandHandler::StreamResult CDCLaunchHandler::StreamData(CDCDataStream &dataStream) {
  uint8_t byte;
  while(dataStream.Get(byte)) {
    if(path_off == MAX_FILENAME) {
      path_off = 0;
      return srError;
    }

    path[path_off++] = byte;

    if(byte == 0) {
      path_off = 0;
      launch_file_from_sd(path);
      return srFinish;
    }
  }

  return srContinue;
}

//////////////////////////////////////////////////////////////////////
// Streaming Code
//  The streaming code works with a simple state machine,
//  current state is in m_parseState, the states parse index is
//  in m_uParseState
//////////////////////////////////////////////////////////////////////

// StreamInit() Initialise state machine
bool FlashLoader::StreamInit(CDCFourCC uCommand) {
  switch(uCommand) {
    case CDCCommandHandler::CDCFourCCMake<'P', 'R', 'O', 'G'>::value:
      dest = Destination::Flash;
      m_parseState = stFilename;
      m_uParseIndex = 0;

      flash_mapped = is_qspi_memorymapped();
      if(flash_mapped) {
        blit_disable_user_code();
        qspi_disable_memorymapped_mode();
      }
      return true;

    case CDCCommandHandler::CDCFourCCMake<'S', 'A', 'V', 'E'>::value:
      dest = Destination::SD;
      m_parseState = stFilename;
      m_uParseIndex = 0;
      blit_disable_user_code();
      return true;

    case CDCCommandHandler::CDCFourCCMake<'_', '_', 'L', 'S'>::value:
      cdc_flash_list();
      return false;
  }

  return false;
}

// StreamData() Handle streamed data
// State machine has three states:
// stFilename : Parse filename
// stLength   : Parse length, this is sent as an ascii string
// stData     : The binary data (.bin file)
CDCCommandHandler::StreamResult FlashLoader::StreamData(CDCDataStream &dataStream)
{
  CDCCommandHandler::StreamResult result = srContinue;
  uint8_t byte;
  while(dataStream.GetStreamLength() && result == srContinue)
  {
    switch (m_parseState)
    {
      case stFilename:
        if(m_uParseIndex < MAX_FILENAME)
        {
          while(result == srContinue && m_parseState == stFilename && dataStream.Get(byte))
          {
            m_sFilename[m_uParseIndex++] = byte;
            if (byte == 0)
            {
              m_parseState = stLength;
              m_uParseIndex = 0;
            }
          }
        }
        else
        {
          debugf("Failed to read filename\n\r");
          result =srError;
        }
      break;


      case stLength:
        if(m_uParseIndex < MAX_FILELEN)
        {
          while(result == srContinue && m_parseState == stLength && dataStream.Get(byte))
          {
            m_sFilelen[m_uParseIndex++] = byte;
            if (byte == 0)
            {
              m_parseState = stRelocs;
              m_uParseIndex = 0;
              char *pEndPtr;
              m_uFilelen = strtoul(m_sFilelen, &pEndPtr, 10);

              if(!m_uFilelen) {
                debugf("Failed to parse filelen\n\r");
                result =srError;
              }
            }
          }
        }
        else
        {
          debugf("Failed to read filelen\n\r");
          result =srError;
        }
      break;

      case stRelocs: {
        uint32_t word;
        if(dest == Destination::SD) {
          // writing to SD, pass the relocs through
          m_parseState = stData;
          if(!prepare_for_data())
            result = srError;
        } else if(m_uParseIndex > 1 && m_uParseIndex == num_relocs + 2) {
          m_parseState = stData;
          m_uParseIndex = 0;

          // got relocs, prepare to flash
          if(!prepare_for_data())
            result = srError;
        } else {
          // break out of loop as we need more data
          if(dataStream.GetStreamLength() < 4)
            return srContinue;

          while(result == srContinue && dataStream.Get(word)) {
            if(m_uParseIndex == 0 && word != 0x4F4C4552 /*RELO*/) {
              debugf("Missing relocation header\n");
              result = srError;
            } else if(m_uParseIndex == 1) {
              num_relocs = word;
              m_uFilelen -= num_relocs * 4 + 8;
              relocation_offsets.clear();
              relocation_offsets.reserve(num_relocs);
            } else if(m_uParseIndex)
              relocation_offsets.push_back(word - qspi_flash_address);

            m_uParseIndex++;

            // done
            if(m_uParseIndex == num_relocs + 2)
              break;
          }
        }
        break;
      }

      case stData:
        while((result == srContinue) && (m_parseState == stData) && (m_uParseIndex <= m_uFilelen) && dataStream.Get(byte)) {
          uint32_t uByteOffset = m_uParseIndex % PAGE_SIZE;
          buffer[uByteOffset] = byte;

          // check buffer needs writing
          volatile uint32_t uWriteLen = 0;
          bool bEOS = false;
          if (m_uParseIndex == m_uFilelen-1) {
            // end of file
            uWriteLen = uByteOffset+1;
            bEOS = true;
          } else if(uByteOffset == PAGE_SIZE-1)
              uWriteLen = PAGE_SIZE; // buffer full
          else {
            // keep filling buffer
            m_uParseIndex++;
            continue;
          }

          if(dest == Destination::SD) {
            // save data
            UINT uWritten;
            FRESULT res = f_write(&file, buffer, uWriteLen, &uWritten);

            if(res != FR_OK || uWritten != uWriteLen) {
              debugf("Failed to save to SDCard\n\r");
              result = srError;
            }
          } else {
            // flash
            uint32_t offset = (m_uParseIndex / PAGE_SIZE) * PAGE_SIZE;

            // relocation patching
            apply_relocs(offset, flash_start_offset, buffer, uWriteLen, relocation_offsets, cur_reloc);

            // save data
            if(!flash_buffer(flash_start_offset + offset, buffer, uWriteLen)) {
              debugf("Failed to write to flash\n\r");
              result = srError;
            }
          }

          progress.update(m_uParseIndex + 1);

          if(bEOS) {
            if(result != srError) {
              while(CDC_Transmit_HS((uint8_t *)"32BL__OK", 8) == USBD_BUSY){}
              if(dest == Destination::Flash) {
                // return the block we used
                uint16_t block = flash_start_offset / qspi_flash_sector_size;
                while(CDC_Transmit_HS((uint8_t *)&block, 2) == USBD_BUSY){}
              }

              result = srFinish;
            }
            progress.hide();
            handle_data_end(result != srError);
          }

          m_uParseIndex++;
          m_uBytesHandled = m_uParseIndex;
        }
      break;
    }
  }

  if(result == srError) {
    progress.hide();

    if(flash_mapped) {
      qspi_enable_memorymapped_mode();
      flash_mapped = false;
    }

    blit_enable_user_code();
  }

  return result;
}

bool FlashLoader::prepare_for_data() {
  // about to start receiving data
  if(dest == Destination::SD) {
    FRESULT res = f_open(&file, m_sFilename, FA_CREATE_ALWAYS | FA_WRITE);
    if(res) {
      debugf("Failed to create file (%s)\n\r", m_sFilename);
      return false;
    } else {
      char buf[300];
      snprintf(buf, 300, "Saving %s to SD card...", m_sFilename);
      progress.show(buf, m_uFilelen);
    }
  } else {
    // flash
    cur_reloc = 0;
    flash_start_offset = get_flash_offset_for_file(m_uFilelen);

    // erase
    erase_qspi_flash(flash_start_offset, m_uFilelen);

    char buf[300];
    snprintf(buf, 300, "Saving %s to flash...", m_sFilename);
    progress.show(buf, m_uFilelen);
  }

  return true;
}

void FlashLoader::handle_data_end(bool success) {
  // done receiving data
  if(dest == Destination::SD) {
    f_close(&file);
    blit_enable_user_code();
  } else {
    // flash
    if(success) {
      // clean up old version(s)
      BlitGameHeader header;
      read_flash_game_header(flash_start_offset, header);

      GameInfo meta;
      meta.size = header.end - qspi_flash_address;
      if(parse_flash_metadata(flash_start_offset, meta)) {
        bool erased_running = cleanup_duplicates(meta, flash_start_offset);

        if(erased_running || strcmp(meta.category, "firmware") == 0) {
          // if we just erased the thing we were running, we need to reset to not crash
          // also need to do firmware updates immediately

          // update the launcher offset
          if(strcmp(meta.category, "launcher") == 0)
            launcher_offset = flash_start_offset;

          blit_switch_execution(flash_start_offset, true);
          return;
        }
      }

      scan_flash();

      if(flash_mapped) {
        qspi_enable_memorymapped_mode();
        flash_mapped = false;
      }
      blit_enable_user_code();

      if(blit_is_launcher_running()) {
        auto game_header = (BlitGameHeader *) (qspi_flash_address + persist.last_game_offset);
        auto init = (BlitInitFunction)((uint8_t *)game_header->init + persist.last_game_offset);
        init(persist.last_game_offset);
      }
    }
  }
}
