#include "map_view.hpp"
#include <functional>
#include <string>
#include "dbc.hpp"
#include "components.hpp"
#include "rand.hpp"
#include "animation.hpp"
#include "systems.hpp"
#include "rand.hpp"
#include <codecvt>
#include <iostream>
#include <fmt/xchar.h>
#include <fstream>

namespace gui {
  using namespace components;
  using namespace guecs;

  MapViewUI::MapViewUI(GameLevel &level) :
    $level(level),
    $paper(textures::get("full_screen_paper"))
  {
  }

  void MapViewUI::update_level(GameLevel &level) {
    $level = level;
  }

  void MapViewUI::init() {
    //auto top_right = overlay.entity("top_right");
    //auto cell = overlay.cell_for(top_right);
    $gui.position(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    $gui.layout(
        "[log_view| *%(200)map_grid | _ ]"
        );

    auto grid = $gui.entity("map_grid");
    $gui.set<Textual>(grid,
        {L"Loading...", 65, {27, 26, 23, 150}, 10});

    $log_to = $gui.entity("log_view");
    $gui.set<Textual>($log_to, {L"Welcome to the Game!", 25, {37, 36, 33}, 25});

    $paper.sprite->setPosition({0, 0});
    $gui.init();
  }

  void MapViewUI::render(sf::RenderWindow &window, int compass_dir) {
    window.draw(*$paper.sprite);

    auto grid = $gui.entity("map_grid");

    std::wstring map_out = System::draw_map($level, 23, 9, compass_dir);

    auto& map_text = $gui.get<Textual>(grid);
    map_text.update(map_out);

    $gui.render(window);
    // $gui.debug_layout(window);
  }

  void MapViewUI::save_map(const std::string& outfile, int compass_dir) {
    std::wstring map_out = System::draw_map(
        $level, $level.map->width(), $level.map->height(), compass_dir);
    dbc::check(map_out.size() > 0, "WHAT? printed map has nothing in it.");

    std::wofstream out(outfile, std::ios::binary);
    std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
    out.imbue(loc);

    out << map_out;
    dbc::check(out.good(), "failed to write map file");
  }

  void MapViewUI::update() {
    if(auto text = $gui.get_if<Textual>($log_to)) {
      //BUG: I'm calling this what it is, fix it
      wstring log_garbage;
      for(auto msg : $messages) {
        log_garbage += msg + L"\n";
      }
      text->update(log_garbage);
    }
  }

  void MapViewUI::log(wstring msg) {
    $messages.push_front(msg);
    if($messages.size() > MAX_LOG_MESSAGES) {
      $messages.pop_back();
    }
    update();
  }
}
