#include <cstring>
#include <forward_list>

#include "pico/stdlib.h"
#include "hardware/flash.h"
#include "hardware/sync.h"
#include "pico/multicore.h"

#ifdef PICO_RP2350
#include "hardware/structs/qmi.h"
#include "hardware/xip_cache.h"
#endif

#include "config.h"
#include "blit_launch.hpp"
#include "file.hpp"
#include "overlay.hpp"

#include "engine/engine.hpp"
#include "engine/file.hpp"

#ifdef PICO_RP2350
#define DEVICE_ID BlitDevice::RP2350
#define FLASH_BASE XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE
#else
#define DEVICE_ID BlitDevice::RP2040
#define FLASH_BASE XIP_NOCACHE_NOALLOC_BASE
#endif

// code related to blit files and launching

#ifdef STORAGE_SD
static const uint32_t flash_end = PICO_FLASH_SIZE_BYTES;
#else
static const uint32_t flash_end = FLASH_STORAGE_OFFSET;
#endif

struct TypeHandlerInfo {
  char type[4]; // should have a null terminator, but the low byte of the offset will always be zero
  uint32_t offset;
};

std::forward_list<TypeHandlerInfo> handlers;

extern int (*do_tick)(uint32_t time);

void disable_user_code();

extern bool core1_started;

static uint32_t requested_launch_offset = 0;
static uint32_t current_game_offset = 0;

static uint32_t get_installed_file_size(uint32_t offset) {
  auto header = (BlitGameHeader *)(FLASH_BASE + offset);

  // check header magic + device
  if(header->magic != blit_game_magic || header->device_id != DEVICE_ID)
    return 0;

  auto size = header->end;

  // check metadata
  auto meta_offset = offset + size;
  if(memcmp((char *)(FLASH_BASE + meta_offset), "BLITMETA", 8) == 0) {
    // add metadata size
    size += *(uint16_t *)(FLASH_BASE + meta_offset + 8) + 10;
  }

  return size;
}

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

#ifdef PICO_RP2350
static uint32_t find_flash_offset(uint32_t requested_size) {
  uint32_t free_off = 0; // 0 is invalid as that's where the loader is

  for(uint32_t off = 256 * 1024; off < flash_end;) {
    auto size = get_installed_file_size(off);

    if(!size) {
      // empty, store offset
      if(!free_off)
        free_off = off;

      off += game_block_size;
      continue;
    }

    if(free_off) {
      // end of free space, check if large enough
      auto found_space = off - free_off;

      if(found_space >= requested_size)
        return free_off;

      free_off = 0;
    }

    // skip to end
    off += calc_num_blocks(size) * game_block_size;
  }

  // last chance
  if(free_off && flash_end - free_off >= requested_size)
    return free_off;

  return 0;
}
#endif

static bool read_file_metadata(void *file, RawMetadata &meta, RawTypeMetadata &type_meta) {
  // read header and check magic
  BlitGameHeader header;
  if(read_file(file, 0, sizeof(header), (char *)&header) != sizeof(header))
    return false;

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

  // read and check metadata header
  auto meta_offset = header.end;

  char meta_header[10];
  if(read_file(file, meta_offset, 10, meta_header) != 10)
    return false;

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

  // read the reset of the metadata header
  if(read_file(file, meta_offset + 10, sizeof(RawMetadata), (char *)&meta) != sizeof(RawMetadata))
    return false;

  // check for type data
  meta_offset += 10 + sizeof(RawMetadata);
  if(read_file(file, meta_offset, 8, meta_header) != 8)
    return false;

  if(memcmp(meta_header, "BLITTYPE", 8) == 0) {
    if(read_file(file, meta_offset + 8, sizeof(RawTypeMetadata), (char *)&type_meta) != sizeof(RawTypeMetadata))
      return false;
  }

  return true;
}

static uint32_t find_installed_blit(RawMetadata &meta) {
  for(uint32_t off = 0; off < flash_end;) {
    auto size = get_installed_file_size(off);

    if(!size) {
      off += game_block_size;
      continue;
    }

    auto header = (BlitGameHeader *)(FLASH_BASE + off);
    auto flash_meta = (RawMetadata *)(FLASH_BASE + off + header->end + 10);

    // check CRC ant title
    if(meta.crc32 == flash_meta->crc32 && strcmp(meta.title, flash_meta->title) == 0) {
      return off;
    }

    off += calc_num_blocks(size) * game_block_size;
  }

  return ~0u;
}

static bool cleanup_duplicates(RawMetadata &meta, uint32_t new_offset) {
  bool ret = false;
  for(uint32_t off = 0; off < flash_end;) {
    auto size = get_installed_file_size(off);

    if(!size) {
      off += game_block_size;
      continue;
    }

    auto header = (BlitGameHeader *)(FLASH_BASE + off);
    auto flash_meta = (RawMetadata *)(FLASH_BASE + off + header->end + 10);

    // check title and author, ignore the current copy of the game
    if(off != new_offset && strcmp(meta.title, flash_meta->title) == 0 && strcmp(meta.author, flash_meta->author) == 0) {
      erase_game(off);

      if(off == current_game_offset)
        ret = true;
    }

    off += calc_num_blocks(size) * game_block_size;
  }

  return ret;
}

// returns lowercased extension
static std::string get_file_ext(const char *path) {
  // get the extension
  std::string_view sv(path);
  auto last_dot = sv.find_last_of('.');
  auto ext = last_dot == std::string::npos ? "" : std::string(sv.substr(last_dot + 1));
  for(auto &c : ext)
    c = tolower(c);

  return ext;
}

// 32blit API

RawMetadata *get_running_game_metadata() {
#ifdef BUILD_LOADER
  if(!current_game_offset)
    return nullptr;

  auto game_ptr = reinterpret_cast<uint8_t *>(FLASH_BASE + current_game_offset);

  auto header = reinterpret_cast<BlitGameHeader *>(game_ptr);

  if(header->magic == blit_game_magic) {
    auto end_ptr = game_ptr + header->end;
    if(memcmp(end_ptr, "BLITMETA", 8) == 0)
      return reinterpret_cast<RawMetadata *>(end_ptr + 10);
  }

#endif
  return nullptr;
}

void create_type_handler_list() {
  handlers.clear();

  blit::api.list_installed_games([](const uint8_t *ptr, uint32_t block, uint32_t size) {
    auto header = (const BlitGameHeader *)ptr;
    auto metadata_ptr = ptr + header->end;

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

    // skip straight to the type block
    metadata_ptr += 10 + sizeof(RawMetadata);

    if(memcmp(metadata_ptr, "BLITTYPE", 8) != 0)
      return;

    // get the type block
    auto type_meta = (const RawTypeMetadata *)(metadata_ptr + 8);

    // loop through filetypes
    for(unsigned i = 0; i < type_meta->num_filetypes; i++) {
      TypeHandlerInfo info;
      memcpy(info.type, type_meta->filetypes[i], 4);
      info.offset = block * game_block_size;

      handlers.emplace_front(info);
    }
  });
}

bool launch_file(const char *path) {
  uint32_t flash_offset = ~0u;

  if(strncmp(path, "flash:/", 7) == 0) // from flash
    flash_offset = atoi(path + 7) * game_block_size;
  else {

    auto ext = get_file_ext(path);

    if(ext != "blit") {
      // with handler
      for(auto &handler : handlers) {
        if(strncmp(ext.data(), handler.type, 4) == 0) {
          flash_offset = handler.offset;
          break;
        }
      }

      // set launch path
    } else {
      // from storage
      auto file = open_file(path, blit::OpenMode::read);

      if(!file)
        return false;

      // read file metadata and try to find matching installed gat
      RawMetadata meta;
      RawTypeMetadata type_meta = {};

      if(read_file_metadata(file, meta, type_meta))
        flash_offset = find_installed_blit(meta);

      // flash if not found
      if(flash_offset == ~0u) {
        BlitWriter writer;

        uint32_t file_offset = 0;
        uint32_t len = get_file_length(file);

        writer.init(len);

        // read in small chunks
        uint8_t buf[FLASH_PAGE_SIZE];

        while(file_offset < len) {
          auto bytes_read = read_file(file, file_offset, FLASH_PAGE_SIZE, (char *)buf);
          if(bytes_read <= 0)
            break;

          if(!writer.write(buf, bytes_read))
            break;

          file_offset += bytes_read;
        }

        close_file(file);

        // didn't write everything, fail launch
        if(writer.get_remaining() > 0)
          return false;

        flash_offset = writer.get_flash_offset();

        cleanup_duplicates(meta, flash_offset);
      } else
        close_file(file);
    }
  }

  auto header = (BlitGameHeader *)(FLASH_BASE + flash_offset);
  // check header magic + device
  if(header->magic != blit_game_magic || header->device_id != DEVICE_ID)
    return false;

  if(!header->init || !header->render || !header->tick)
    return false;

  requested_launch_offset = flash_offset;
  return true;
}

blit::CanLaunchResult can_launch(const char *path) {
#ifdef BUILD_LOADER
  if(strncmp(path, "flash:/", 7) == 0) {
    // assume anything flashed is compatible for now
    return blit::CanLaunchResult::Success;
  }

  // get the extension
  auto ext = get_file_ext(path);

  if(ext == "blit") {
    BlitGameHeader header;
    auto file = open_file(path, blit::OpenMode::read);

    if(!file)
      return blit::CanLaunchResult::InvalidFile;

    auto bytes_read = read_file(file, 0, sizeof(header), (char *)&header);

    if(bytes_read == sizeof(header) && header.magic == blit_game_magic && header.device_id == DEVICE_ID) {
      close_file(file);
      return blit::CanLaunchResult::Success;
    }

    close_file(file);
    return blit::CanLaunchResult::IncompatibleBlit;
  }

  // check handlers
  for(auto &handler : handlers) {
    if(strncmp(ext.data(), handler.type, 4) == 0) {
      return blit::CanLaunchResult::Success;
    }
  }

#endif

  return blit::CanLaunchResult::UnknownType;
}

void launch_pre_init() {
  // reset api state before launching new game
  blit::api_data.buttons = {0, 0, 0};

  blit::api_data.LED = {0, 0, 0};
  blit::api_data.vibration = 0.0f;
  blit::api_data.message_received = nullptr;
  blit::api_data.i2c_completed = nullptr;

  for(int i = 0; i < CHANNEL_COUNT; i++)
    blit::api.channels[i] = blit::AudioChannel();
}

void delayed_launch() {
  if(!requested_launch_offset)
    return;

  auto header = (BlitGameHeader *)(FLASH_BASE + requested_launch_offset);

#ifdef PICO_RP2350
  uint32_t header_offset = *(uint32_t *)(FLASH_BASE + requested_launch_offset + sizeof(BlitGameHeader));
  if(header_offset != requested_launch_offset) {
    // setup translation
    uint32_t size = 4 * 1024 * 1024; // TODO: use (rounded) blit size
    qmi_hw->atrans[1] = (size >> 12) << QMI_ATRANS1_SIZE_LSB
                      | (requested_launch_offset >> 12) << QMI_ATRANS1_BASE_LSB;

    // invalidate cache
    xip_cache_invalidate_range(4 * 1024 * 1024, size);

    // FIXME: handle previous blit also using translation on failure
  }
#endif

  // save in case launch fails
  uint32_t last_game_offset = current_game_offset;

  current_game_offset = requested_launch_offset;
  requested_launch_offset = 0;

  launch_pre_init();

  if(!header->init(0)) {
    blit::debugf("failed to init game!\n");
    current_game_offset = last_game_offset;
    return;
  }

  blit::render = header->render;
  do_tick = header->tick;
}

void list_installed_games(std::function<void(const uint8_t *, uint32_t, uint32_t)> callback) {
  for(uint32_t off = 0; off < flash_end;) {
    auto size = get_installed_file_size(off);

    if(!size) {
      off += game_block_size;
      continue;
    }

    callback((const uint8_t *)(FLASH_BASE + off), off / game_block_size, size);

    off += calc_num_blocks(size) * game_block_size;
  }
}

void erase_game(uint32_t offset) {
#ifdef BUILD_LOADER
  // check alignment
  if(offset & (game_block_size - 1))
    return;

  // check in bounds
  if(offset >= flash_end)
    return;

  auto size = get_installed_file_size(offset);

  // fall back to one block if size unknown
  auto num_blocks = size == 0 ? 1 : calc_num_blocks(size);

  // we can't display progress unless we break up the erase...
  set_render_overlay_enabled(true);
  set_overlay_message("Erasing flash...");
  set_overlay_progress(0, 0);
  // make sure the message is displayed before we disable interrupts/core1
  overlay_try_render(true);

  // do erase
  auto status = save_and_disable_interrupts();

  if(core1_started)
    multicore_lockout_start_blocking(); // pause core1

  // the real erase size is smaller than the one baked into the API...
  static_assert(game_block_size % FLASH_SECTOR_SIZE == 0);
  flash_range_erase(offset, num_blocks * game_block_size);

  if(core1_started)
    multicore_lockout_end_blocking(); // resume core1

  restore_interrupts(status);

  set_render_overlay_enabled(false);

  // clear out any handler entries
  auto prev = handlers.before_begin();
  for(auto it = handlers.begin(); it != handlers.end();) {
    if(it->offset == offset)
      it = handlers.erase_after(prev);
    else
      prev = it++;
  }
#endif
}

void *get_type_handler_metadata(const char *filetype) {
#ifdef BUILD_LOADER
  for(auto &handler : handlers) {
    if(strncmp(filetype, handler.type, 4) == 0) {
      auto ptr = (const uint8_t *)(FLASH_BASE + handler.offset);
      auto header = (const BlitGameHeader *)ptr;
      auto metadata_ptr = ptr + header->end;

      // this really shouldn't fail if it's in the list, but be safe
      if(memcmp(metadata_ptr, "BLITMETA", 8) == 0)
        return (void *)metadata_ptr;
    }
  }
#endif
  return nullptr;
}

// .blit file writer
void BlitWriter::init(uint32_t file_len) {
  this->file_len = file_len;
  file_offset = flash_offset = 0;
}

bool BlitWriter::write(const uint8_t *buf, uint32_t len) {
  if(!flash_offset) {
    if(!prepare_write(buf))
      return false;
  }

  if(file_offset >= file_len)
    return false;

  // write page
  auto status = save_and_disable_interrupts();

  if(core1_started)
    multicore_lockout_start_blocking(); // pause core1

  // assuming len <= page size and buf size == page size
  flash_range_program(flash_offset + file_offset, buf, FLASH_PAGE_SIZE);

  if(core1_started)
    multicore_lockout_end_blocking(); // resume core1

  restore_interrupts(status);

  file_offset += len;

  return true;
}

void BlitWriter::cleanup_duplicates() {
  auto header = (BlitGameHeader *)(FLASH_BASE + flash_offset);
  auto meta = (RawMetadata *)(FLASH_BASE + flash_offset + header->end + 10);
  ::cleanup_duplicates(*meta, flash_offset);
}

uint32_t BlitWriter::get_offset() const {
  return file_offset;
}

uint32_t BlitWriter::get_length() const {
  return file_len;
}

uint32_t BlitWriter::get_remaining() const {
  return file_len - file_offset;
}

uint32_t BlitWriter::get_flash_offset() const {
  return flash_offset;
}

bool BlitWriter::prepare_write(const uint8_t *buf) {
  auto header = (BlitGameHeader *)buf;

  if(header->magic != blit_game_magic || header->device_id != DEVICE_ID) {
    blit::debugf("Invalid blit header!");
    return false;
  }

  // currently non-relocatable, so base address is stored after header
  flash_offset = *(uint32_t *)(buf + sizeof(BlitGameHeader));
  flash_offset &= 0xFFFFFF;

#ifdef PICO_RP2350
  if(flash_offset == 4 * 1024 * 1024) {
    // we can use address translation for this, so flash in any free space
    flash_offset = find_flash_offset(file_len);
  }

  if(!flash_offset) {
    blit::debugf("Not enough space!");
    return false;
  }
#endif

  disable_user_code();

  // erase flash
  auto status = save_and_disable_interrupts();

  if(core1_started)
    multicore_lockout_start_blocking(); // pause core1

  auto erase_size = ((file_len - 1) / FLASH_SECTOR_SIZE) + 1;
  flash_range_erase(flash_offset, erase_size * FLASH_SECTOR_SIZE);

  if(core1_started)
    multicore_lockout_end_blocking(); // resume core1

  restore_interrupts(status);

  return true;
}
