#pragma once
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <ftxui/component/component.hpp>
#include <ftxui/screen/screen.hpp>
#include <ftxui/dom/canvas.hpp>
#include "ftxui/component/component.hpp"  // for Button, operator|=, Renderer, Vertical, Modal
#include "ftxui/component/screen_interactive.hpp"  // for ScreenInteractive, Component
#include "ftxui/dom/elements.hpp"  // for operator|, separator, text, size, Element, vbox, border, GREATER_THAN, WIDTH, center, HEIGHT
#include <locale>
#include <string>
#include "map.hpp"
#include "dinkyecs.hpp"
#include "components.hpp"
#include "sound.hpp"
#include "render.hpp"
#include "panel.hpp"
#include "lights.hpp"

using std::string;
using ftxui::Canvas, ftxui::Component, ftxui::Screen, ftxui::Button;
using lighting::LightRender;

struct ActionLog {
  std::deque<std::string> messages;

  void log(std::string msg) {
    messages.push_front(msg);
    if(messages.size() > 20) {
      messages.pop_back();
    }
  }
};

struct UnDumbTSS {
  sf::Texture texture;
  sf::Sprite sprite;
  sf::Shader shader;


  sf::Shader& load_shader(string filename) {
    bool good = shader.loadFromFile(filename, sf::Shader::Fragment);
    dbc::check(good, "shader could not be loaded");
    return shader;
  }
};


class InventoryUI : public Panel {
  public:
  InventoryUI() : Panel(INVENTORY_PIXEL_X, INVENTORY_PIXEL_Y, INVENTORY_WIDTH, INVENTORY_HEIGHT) {}
  void create_render();
};

class StatusUI : public Panel {
  public:
  ActionLog $log;
  string $status_text = "NOT DEAD";
  DinkyECS::World& $world;

  StatusUI(DinkyECS::World& world) :
    Panel(0, 0, STATUS_UI_WIDTH, STATUS_UI_HEIGHT),
    $log({{"Welcome to the game!"}}),
    $world(world) {}

  void create_render();
  void log(string msg) {
    $log.log(msg);
  }
};

class MapViewUI : public Panel {
  public:
    Canvas $canvas;
    DinkyECS::World& $world;
    LightRender& $lights;
    Map& $game_map;

    MapViewUI(DinkyECS::World& world, LightRender& lights, Map& game_map);
    void create_render();
    void resize_canvas();
};

class GUI {
  DinkyECS::World& $world;
  Map& $game_map;
  StatusUI $status_ui;
  LightRender $lights;
  MapViewUI $map_view;
  InventoryUI $inventory_ui;
  Canvas $canvas;
  bool $show_modal = false;
  Component $test_button;
  SoundManager $sounds;
  SFMLRender $renderer;
  UnDumbTSS $paused;
  std::vector<Panel*> $panels;

public:
  GUI(DinkyECS::World& world, Map& game_map);
  // disable copying
  GUI(GUI &gui) = delete;

  void resize_map(int new_size);
  void create_renderer();
  void render_scene();
  bool handle_ui_events();
  void handle_world_events();
  void draw_screen(bool clear=true, float map_off_x=0.0f, float map_off_y=0.0f);
  void run_systems();
  void save_world();
  void shake();
  void shutdown();
  int main(bool run_once=false);

  void pause_screen();
  void draw_paused();
  void init_shaders();
};
