#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <list>

#include "launcher.hpp"
#include "assets.hpp"

#include "engine/api_private.hpp"
#include "graphics/color.hpp"

#include "executable.hpp"
#include "metadata.hpp"
#include "dialog.hpp"

#include "theme.hpp"

#include "credits.hpp"

using namespace blit;

struct PathSave {
  char last_path[512];
};

static const int path_save_slot = 256;

static Dialog dialog;

const Font launcher_font(font8x8);

constexpr uint32_t qspi_flash_sector_size = 64 * 1024;

static Screen current_screen = Screen::main;

static bool show_fps = false;
static bool sd_detected = true;
static Vec2 file_list_scroll_offset(10.0f, 0.0f);
static Point game_info_offset(120, 20);
static Point game_actions_offset(game_info_offset.x + 128 + 8, 28);
static float directory_list_scroll_offset = 0.0f;

static std::vector<GameInfo> game_list;
static std::list<DirectoryInfo> directory_list;
static std::list<DirectoryInfo>::iterator current_directory;

static SortBy file_sort = SortBy::name;

static GameInfo selected_game;
static BlitGameMetadata selected_game_metadata;

static Surface *spritesheet;
static Surface *screenshot;

static AutoRepeat ar_button_up(250, 600);
static AutoRepeat ar_button_down(250, 600);
static AutoRepeat ar_button_left(0, 0);
static AutoRepeat ar_button_right(0, 0);

#ifndef PICO_BUILD
static uint8_t screenshot_buf[320 * 240 * 3];
#endif

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

// insertion sort
template <class Iterator, class Compare>
static void insertion_sort(Iterator first, Iterator last, Compare comp) {
  if(last - first < 2)
    return;

  for(auto it = first + 1; it != last; ++it) {
    auto temp = it;

    while(temp != first && comp(*temp, *(temp - 1))) {
      std::swap(*temp, *(temp - 1));
      --temp;
    }
  }
}

static bool parse_file_metadata(const std::string &filename, BlitGameMetadata &metadata, bool unpack_images = false) {
  blit::File f(filename);

  if(!f.is_open())
    return false;

  uint32_t offset = 0;

  uint8_t buf[sizeof(BlitGameHeader)];
  auto read = f.read(offset, sizeof(buf), (char *)&buf);

  // skip relocation data
  if(memcmp(buf, "RELO", 4) == 0) {
    uint32_t num_relocs;
    f.read(4, 4, (char *)&num_relocs);

    offset = num_relocs * 4 + 8;
    // re-read header
    read = f.read(offset, sizeof(buf), (char *)&buf);
  }

  // game header - skip to metadata
  if(memcmp(buf, "BLITMETA", 8) != 0) {
    auto &header = *(BlitGameHeader *)buf;
    if(read == sizeof(BlitGameHeader) && header.magic == blit_game_magic) {
      offset += (header.end & 0x1FFFFFF);
      read = f.read(offset, 10, (char *)buf);
    }
  }

  if(read >= 10 && memcmp(buf, "BLITMETA", 8) == 0) {
    // don't bother reading the whole thing if we don't want the images
    auto metadata_len = unpack_images ? *reinterpret_cast<uint16_t *>(buf + 8) : sizeof(RawMetadata);

    uint8_t metadata_buf[0xFFFF];
    f.read(offset + 10, metadata_len, (char *)metadata_buf);

    parse_metadata(reinterpret_cast<char *>(metadata_buf), metadata_len, metadata, unpack_images);

    return true;
  }

  return false;
}

static void sort_file_list() {
    using Iterator = std::vector<GameInfo>::iterator;
    using Compare = bool(const GameInfo &, const GameInfo &);

    if (file_sort == SortBy::name) {
      // Sort by filename
      insertion_sort<Iterator, Compare>(game_list.begin(), game_list.end(), [](const auto &a, const auto &b) { return a.title < b.title; });
    }

    if (file_sort == SortBy::size) {
      // Sort by filesize
      insertion_sort<Iterator, Compare>(game_list.begin(), game_list.end(), [](const auto &a, const auto &b) { return a.size < b.size; });
    }
}

static void load_file_list(const std::string &directory) {

  game_list.clear();

  auto files = list_files(directory, [&](auto &file) {
    if(file.flags & FileFlags::directory)
      return false;

    if(file.name[0] == '.') // hidden file
      return false;

    auto path = directory == "/" ? file.name : directory + "/" + file.name;
    auto res = api.can_launch(path.c_str());

    if(res == CanLaunchResult::UnknownType) {
      // special case for images
      auto last_dot = file.name.find_last_of('.');

      auto ext = last_dot == std::string::npos ? "" : file.name.substr(last_dot + 1);

      for(auto &c : ext)
        c = tolower(c);

      if(ext == "bmp" || ext == "blim")
        return true;
    }

    // will filter incompatible later
    return res == CanLaunchResult::Success || res == CanLaunchResult::IncompatibleBlit;
  });

  game_list.reserve(files.size()); // worst case

  for(auto &file : files) {
    auto last_dot = file.name.find_last_of('.');

    auto ext = last_dot == std::string::npos ? "" : file.name.substr(last_dot + 1);

    for(auto &c : ext)
      c = tolower(c);

    GameInfo game;
    game.title = file.name.substr(0, file.name.length() - ext.length() - 1);
    game.filename = directory == "/" ? file.name : directory + "/" + file.name;
    game.size = file.size;

    if(ext == "blit") {
      game.type = GameType::game;
      game.can_launch = api.can_launch(game.filename.c_str()) == CanLaunchResult::Success;

      // check for metadata
      BlitGameMetadata meta;
      if(parse_file_metadata(game.filename, meta))
        game.title = meta.title;

    } else  if(ext == "bmp" || ext == "blim") {
      game.type = GameType::screenshot;

      // Special case check for an installed handler for these types, ie: a sprite editor
      game.can_launch = api.get_type_handler_metadata && api.get_type_handler_metadata(ext.c_str());
    } else {
      // it's launch-able so there must be a handler
      game.type = GameType::file;
      strncpy(game.ext, ext.c_str(), 5);
      game.ext[4] = 0;
      game.can_launch = true;

      // check for a metadata file (fall back to handler's metadata)
      BlitGameMetadata meta;
      auto meta_filename = game.filename + ".blmeta";
      if(parse_file_metadata(meta_filename, meta))
        game.title = meta.title;
    }

    game_list.push_back(game);
  }

  int total_items = (int)game_list.size();
  if(selected_menu_item >= total_items)
    selected_menu_item = std::max(0, total_items - 1);

  // probably doesn't do anything...
  game_list.shrink_to_fit();

  sort_file_list();
}

static void load_directory_list(const std::string &directory) {
  directory_list.clear();

  auto dir_filter = [](const FileInfo &info){
    if(!(info.flags & FileFlags::directory))
      return false;

    if(info.name.compare("System Volume Information") == 0 || info.name[0] == '.')
      return false;

    return true;
  };

  for(auto &folder : ::list_files(directory, dir_filter))
    directory_list.push_back({folder.name, 0, 0});

  directory_list.sort([](const auto &a, const auto &b) { return a.name > b.name; });

  directory_list.push_front({"/", 0, 0});
  directory_list.push_front({"flash:", 0, 0});

  // measure positions
  int x = 0;
  for(auto &dir : directory_list) {
    dir.x = x;
    dir.w = screen.measure_text(dir.name == "/" ? "ROOT" : dir.name, launcher_font).w;

    x += dir.w + 10;
  }
}

static void load_current_game_metadata() {
  bool loaded = false;

  if(!game_list.empty()) {
    selected_game = game_list[selected_menu_item];

    if(selected_game.type == GameType::file) {
      // not a .blit - look for a metadata file
      auto meta_filename = selected_game.filename + ".blmeta";
      if(!parse_file_metadata(meta_filename, selected_game_metadata, true)) {
        // fallback to handler metadata/placeholders
        auto handler_meta = (char *)api.get_type_handler_metadata(selected_game.ext);
        auto len = *reinterpret_cast<uint16_t *>(handler_meta + 8);
        parse_metadata(handler_meta + 10, len, selected_game_metadata, true);

        selected_game_metadata.description = "Launches with: " + selected_game_metadata.title;
        selected_game_metadata.title = selected_game.title;
        selected_game_metadata.author = "";
        selected_game_metadata.version = "";
      }
      loaded = true;
    } else
      loaded = parse_file_metadata(selected_game.filename, selected_game_metadata, true);
  }

#ifndef PICO_BUILD
  if(selected_game.type == GameType::screenshot) {
    // Free any old buffers
    if(screenshot) {
      delete[] screenshot->palette;
      delete screenshot;
      screenshot = nullptr;
    }
    // Load the new screenshot
    screenshot = Surface::load(selected_game.filename, screenshot_buf, sizeof(screenshot_buf));
  } else {
    // Not showing a screenshot, free the buffers
    if(screenshot) {
      delete[] screenshot->palette;
      delete screenshot;
      screenshot = nullptr;
    }
  }
#endif

  // no valid metadata, reset
  if(!loaded) {
    selected_game_metadata.free_surfaces();
    selected_game_metadata = BlitGameMetadata();
  }
}

static bool launch_current_game() {
  // save last file launched
  PathSave save{};
  strncpy(save.last_path, selected_game.filename.c_str(), sizeof(save.last_path) - 1);
  write_save(save, path_save_slot);

  if(!api.launch)
    return false;

  return api.launch(selected_game.filename.c_str());
}

static void delete_current_game() {
  dialog.show("Confirm", "Really delete " + selected_game.title + "?", [](bool yes){
    if(yes) {
      if(selected_game.filename.compare(0, 7, "flash:/") == 0)
        api.erase_game(std::stoi(selected_game.filename.substr(7)) * qspi_flash_sector_size);

      ::remove_file(selected_game.filename);

      load_file_list(current_directory->name);
      load_current_game_metadata();
    }
  });
}

static void init_lists() {
  load_directory_list("/");
  current_directory = directory_list.begin();

  load_file_list(current_directory->name);

  load_current_game_metadata();
}

static void scan_flash() {
  if(api.list_installed_games) {
    api.list_installed_games([](const uint8_t *ptr, uint32_t block, uint32_t size){
      File::add_buffer_file("flash:/" + std::to_string(block) + ".blit", ptr, size);
    });
  }
}

void init() {
  set_screen_mode(ScreenMode::hires);
  screen.clear();

  // shrink the filename column on narrower screens
  if(screen.bounds.w < game_actions_offset.x + 24) {
    int diff = (game_actions_offset.x + 24) - screen.bounds.w;
    game_info_offset.x -= diff;
    game_actions_offset.x -= diff;
  }

  selected_menu_item = 0;

  init_theme();

  spritesheet = Surface::load(sprites);

  scan_flash();
  init_lists();

  // restore previously selected file
  PathSave save;
  save.last_path[0] = 0;

  if(read_save(save, path_save_slot)) {
    auto path = std::string_view(save.last_path);
    auto slash = path.find_first_of('/');

    std::string_view dir;

    if(slash == std::string_view::npos)
      dir = "/";
    else
      dir = path.substr(0, slash);

    // select dir
    for(auto it = directory_list.begin(); it != directory_list.end(); ++it) {
      if(it->name == dir) {
        if(it != current_directory)
          load_file_list(it->name);

        current_directory = it;
        break;
      }
    }

    // select file
    for(auto it = game_list.begin(); it != game_list.end(); ++it) {
      if(it->filename == path) {
        selected_menu_item = it - game_list.begin();
        break;
      }
    }

    load_current_game_metadata();
  }

  credits::prepare();
}

static void swoosh(uint32_t time, float t1, float t2, float s1, float s2, int t0, int offset_y=120, int size=60, int alpha=64) {
  constexpr int swoosh_resolution = 32;
  int w = (screen.bounds.w + swoosh_resolution - 1) / swoosh_resolution;

  for(auto x = 0; x < w; x++) {
    float t_a = (x / s1) + float(time + t0) / t1;
    float t_b = (x / s2) + float(time + t0) / t2;

    int y1 = sinf(t_a) * size;
    int y2 = sinf(t_b) * size;

    if(y1 > y2) std::swap(y1, y2);

    y1 += offset_y;
    y2 += offset_y + 2;

    int range = y2 - y1;

    for(auto y = 0; y <= range; y++) {
      if(y > range / 2) {
        screen.pen.a = alpha - (alpha * y / range);
      } else {
        screen.pen.a = alpha * y / range;
      }
      // This is an optimisation, not an aesthetic choice!
      screen.h_span(Point(x * swoosh_resolution,  y1 + y), swoosh_resolution);
    }
  }
}

static void render_fps(uint32_t us_start) {
  if(!show_fps) return;
  // draw FPS meter
  uint32_t us_end = now_us();
  uint32_t us_elapsed = us_diff(us_start, us_end);
  screen.mask = nullptr;

  screen.pen = Pen(0, 0, 0);
  screen.rectangle(Rect(Point(0, screen.bounds.h - 14), Size(game_info_offset.x - 10, 14)));

  screen.pen = Pen(255, 0, 0);
  for (unsigned int i = 0; i < us_elapsed / 1000; i++) {
    screen.pen = Pen(i * 5, 255 - (i * 5), 0);
    screen.rectangle(Rect(i * 3 + 1, screen.bounds.h - 3, 2, 2));
  }

  screen.pen = Pen(255, 255, 255);
  screen.text(std::to_string(us_elapsed), minimal_font, Point(0, screen.bounds.h - 12));
}

static void render_directory_list() {
  // adjust alignment rect for vertical spacing
  const int text_align_height = ROW_HEIGHT + launcher_font.spacing_y;

  // list folders
  if(directory_list.empty())
    return;

  int width = screen.bounds.w - game_info_offset.x - 10;

  // darken behind if showing screenshot
  if(screenshot) {
    screen.pen = theme.color_background;
    screen.pen.a = 150;
    screen.rectangle(Rect(game_info_offset.x - 10, 0, width + 20, 20));
  }

  screen.clip = Rect(game_info_offset.x, 5, width, text_align_height);

  for(auto &directory : directory_list) {
    if(directory.name == current_directory->name)
      screen.pen = theme.color_accent;
    else
      screen.pen = theme.color_text;

    int x = 120 + (width / 2) + directory.x - directory_list_scroll_offset;
    screen.text(directory.name == "/" ? "ROOT" : directory.name, launcher_font, Rect(x, 5, width, text_align_height), true, TextAlign::center_v);
  }

  screen.clip = Rect(Point(0, 0), screen.bounds);
}

static void render_file_list() {
  // adjust alignment rect for vertical spacing
  const int text_align_height = ROW_HEIGHT + launcher_font.spacing_y;

  if(game_list.empty())
    return;

  // background
  if(screenshot) {
    // darken if showing screenshot
    screen.pen = theme.color_background;
    screen.pen.a = 150;
  } else
    screen.pen = theme.color_overlay;

  screen.rectangle(Rect(0, 0, game_info_offset.x - 10, screen.bounds.h));

  screen.clip = Rect(0, 0, game_info_offset.x - 20, screen.bounds.h);
  int title_w = screen.clip.w - file_list_scroll_offset.x;

  int y = (screen.bounds.h / 2) - 5 - file_list_scroll_offset.y;
  int i = 0;

  for(auto &file : game_list) {
    if(i++ == selected_menu_item)
      screen.pen = theme.color_accent;
    else
      screen.pen = theme.color_text;

    screen.text(file.title, launcher_font, Rect(file_list_scroll_offset.x, y, title_w, text_align_height), true, TextAlign::center_v);
    y += ROW_HEIGHT;
  }
  screen.clip = Rect(Point(0, 0), screen.bounds);
}

static void render_screenshot() {
  if(screenshot->bounds.w == screen.bounds.w) {
    // full screen image
    screen.blit(screenshot, Rect(Point(0, 0), screenshot->bounds), Point(0, 0));
  } else if(screenshot->bounds == Size(128, 128)) {
    // standard spritesheet size, show in info column
    screen.pen = Pen(0, 0, 0, 255);
    screen.rectangle(Rect(game_info_offset, Size(128, 128)));
    screen.blit(screenshot, Rect(Point(0, 0), screenshot->bounds), game_info_offset);
  } else {
    screen.stretch_blit(screenshot, Rect(Point(0, 0), screenshot->bounds), Rect(Point(0, 0), screen.bounds));
  }
}

static void render_game_info() {
  // run game / launch file
  if(selected_game.can_launch) {
    screen.sprite(1, Point(game_actions_offset.x, game_actions_offset.y + 12));
    screen.sprite(0, Point(game_actions_offset.x + 10, game_actions_offset.y + 12), SpriteTransform::R90);
  }

  // game info
  if(selected_game_metadata.splash)
    screen.blit(selected_game_metadata.splash, Rect(Point(0, 0), selected_game_metadata.splash->bounds), game_info_offset);

  screen.pen = theme.color_accent;
  std::string wrapped_title = screen.wrap_text(selected_game_metadata.title, screen.bounds.w - game_info_offset.x - 10, launcher_font);

  Size title_size = screen.measure_text(wrapped_title, launcher_font);
  screen.text(wrapped_title, launcher_font, Point(game_info_offset.x, game_info_offset.y + 104));

  Rect desc_rect(game_info_offset.x, game_info_offset.y + 108 + title_size.h, screen.bounds.w - game_info_offset.x - 10, 64);

  screen.pen = theme.color_text;
  std::string wrapped_desc = screen.wrap_text(selected_game_metadata.description, desc_rect.w, launcher_font);
  screen.text(wrapped_desc, launcher_font, desc_rect);

  screen.text(selected_game_metadata.author, minimal_font, Point(game_info_offset.x, screen.bounds.h - 32));
  screen.text(selected_game_metadata.version, minimal_font, Point(game_info_offset.x, screen.bounds.h - 24));

  int num_blocks = calc_num_blocks(selected_game.size);
  char buf[20];
  snprintf(buf, 20, "%i block%s", num_blocks, num_blocks == 1 ? "" : "s");
  screen.text(buf, minimal_font, Point(game_info_offset.x, screen.bounds.h - 16));

  if(!selected_game.can_launch) {
    screen.pen = {255, 0, 0};
    screen.text("INCOMPATIBLE", minimal_font, Point(screen.bounds.w - 10, screen.bounds.h - 16), true, TextAlign::top_right);
  }
}

void render(uint32_t time) {
  uint32_t us_start = now_us();
  screen.sprites = spritesheet;

  screen.pen = theme.color_background;
  screen.clear();

  // display background swoosh if not displaying a screenshot or the credits
  if(current_screen != Screen::screenshot && current_screen != Screen::credits && selected_game.type != GameType::screenshot) {
    screen.pen = Pen(255, 255, 255);
    swoosh(time, 5100.0f, 3900.0f, 1900.0f, 900.0f, 3500);
    screen.pen = theme.color_accent;
    swoosh(time, 5000.0f, 3000.0f, 1000.0f, 1000.0f, 0);
    screen.pen = Pen(~theme.color_accent.r, ~theme.color_accent.g, ~theme.color_accent.b);
    swoosh(time, 5100.0f, 3900.0f, 900.0f, 1100.0f, 5000);
  }

  // display image preview
  if(!game_list.empty() && screenshot)
    render_screenshot();

  // don't display lists over fullscreen screenshot
  if(current_screen != Screen::screenshot) {
    render_directory_list();
    render_file_list();
  }

  // current file info/actions
  if(!game_list.empty()) {
    // delete
    screen.sprite(2, Point(game_actions_offset.x, game_actions_offset.y));
    screen.sprite(0, Point(game_actions_offset.x + 10, game_actions_offset.y));

    if(selected_game.type == GameType::screenshot) {
      if(screenshot && screenshot->bounds == Size(128, 128)) {
        if(selected_game.can_launch){
          // edit (in sprite editor, presumably)
          screen.sprite(1, Point(game_actions_offset.x, game_actions_offset.y + 12));
          screen.sprite(0, Point(game_actions_offset.x + 10, game_actions_offset.y + 12), SpriteTransform::R90);
        }
      } else if (current_screen == Screen::screenshot) {
        // exit fullscreen
        screen.sprite(5, Point(game_actions_offset.x, game_actions_offset.y + 12));
        screen.sprite(0, Point(game_actions_offset.x + 10, game_actions_offset.y + 12), SpriteTransform::R180);
      } else if(screenshot) {
        // view screenshot fullscreen
        screen.sprite(4, Point(game_actions_offset.x, game_actions_offset.y + 12));
        screen.sprite(0, Point(game_actions_offset.x + 10, game_actions_offset.y + 12), SpriteTransform::R90);
      }
    } else {
      render_game_info();
    }
  } else {
    screen.pen = theme.color_text;

    if(current_directory->name != "flash:" && !blit::is_storage_available())
      screen.text("No SD Card\nDetected.", launcher_font, Point(screen.bounds.w / 2, screen.bounds.h / 2), true, TextAlign::center_center);
    else
      screen.text("No Games Found.", launcher_font, Point(screen.bounds.w / 2, screen.bounds.h / 2), true, TextAlign::center_center);
  }

  if (current_screen == Screen::credits) {
    credits::render();
  }

  //progress.draw();
  dialog.draw();
  render_fps(us_start);
}

void update(uint32_t time) {

  if(blit::is_storage_available() != sd_detected) {
    init_lists();
    sd_detected = blit::is_storage_available();
  }

  bool button_a = buttons.released & Button::A;
  bool button_b = buttons.pressed & Button::B;
  bool button_x = buttons.pressed & Button::X;
  bool button_y = buttons.pressed & Button::Y;
  bool button_menu = buttons.pressed & Button::MENU;
  bool button_up = ar_button_up.next(time, buttons.state & Button::DPAD_UP || joystick.y < -0.2f);
  bool button_down = ar_button_down.next(time, buttons.state & Button::DPAD_DOWN || joystick.y > 0.2f);
  bool button_left = ar_button_left.next(time, buttons.state & Button::DPAD_LEFT || joystick.x < -0.5f);
  bool button_right = ar_button_right.next(time, buttons.state & Button::DPAD_RIGHT || joystick.x > 0.5f);

  if(dialog.update())
    return;

  // update/close credits
  if (current_screen == Screen::credits) {
    credits::update(time);

    if (button_menu) {
      current_screen = Screen::main;
    }

    if(button_y) {
      show_fps = !show_fps;
    }

    return;
  }

  // display credits
  if (button_menu) {
    credits::reset_scrolling();
    current_screen = Screen::credits;
  }

  // scroll through file list
  int total_items = (int)game_list.size();

  auto old_menu_item = selected_menu_item;

  if(button_up) {
    selected_menu_item--;
    if(selected_menu_item < 0) {
      selected_menu_item = total_items - 1;
    }
  }

  if(button_down) {
    selected_menu_item++;
    if(selected_menu_item > total_items - 1) {
      selected_menu_item = 0;
    }
  }

  if(current_screen == Screen::screenshot) {
    // b to exit full screen screenshot view
    if(button_b) {
      current_screen = Screen::main;
    }
  } else {
    // scroll through directories
    if(button_left) {
      if(current_directory == directory_list.begin())
        current_directory = --directory_list.end();
      else
        --current_directory;
    }

    if(button_right) {
      current_directory++;
      if(current_directory == directory_list.end()) {
        current_directory = directory_list.begin();
      }
    }

    // reload file list if dir changed
    if(button_left || button_right) {
      load_file_list(current_directory->name);

      selected_menu_item = 0;
      old_menu_item = -1;
    }

    // toggle sort mode
    if (button_y) {
      file_sort = file_sort == SortBy::name ? SortBy::size : SortBy::name;
      sort_file_list();
    }
  }

  // scroll list towards selected item
  file_list_scroll_offset.y += ((selected_menu_item * ROW_HEIGHT) - file_list_scroll_offset.y) / 5.0f;

  directory_list_scroll_offset += (current_directory->x + current_directory->w / 2 - directory_list_scroll_offset) / 5.0f;

  if(game_list.empty())
    return;

  // load metadata for selected item
  if(selected_menu_item != old_menu_item) {
    load_current_game_metadata();
  }

  // paranoid bail out if you're browsing screenshots full screen and come across a game
  if(selected_game.type != GameType::screenshot && current_screen == Screen::screenshot) {
    current_screen = Screen::main;
  }

  // delete current game / screenshot
  if(button_x) {
    delete_current_game();
  }

  // launch game / show screenshot fullscreen
  if(button_a) {
    if(selected_game.type == GameType::screenshot && !selected_game.can_launch) {
      current_screen = Screen::screenshot;
    } else if(selected_game.can_launch) {
      if(!launch_current_game())
        dialog.show("Error!", "Failed to launch " + selected_game.filename, [](bool){}, false);
    }
  }
}
