#include "ui/start_screen.h"
#include "app.h"
#include "lua/game_engine.h"
#include "ui/game_screen.h"

#include <wx/filedlg.h>
#include <wx/image.h>
#include <wx/mstream.h>

wxDECLARE_APP(cApp);

enum { ID_OpenCartridge = 1001, ID_StartGame = 1002 };

cStartScreen::cStartScreen()
    : wxFrame(nullptr, wxID_ANY, "Wherigo Player", wxDefaultPosition,
              wxSize(800, 800)),
      m_gameFrame(nullptr), m_cartridgeLoaded(false) {

  // Menu
  auto *menuFile = new wxMenu;
  menuFile->Append(ID_OpenCartridge, "Cartridge öffnen...\tCtrl+O");
  menuFile->AppendSeparator();
  menuFile->Append(wxID_EXIT, "Beenden");

  auto *menuHelp = new wxMenu;
  menuHelp->Append(wxID_ABOUT, "Über...");

  auto *menuBar = new wxMenuBar;
  menuBar->Append(menuFile, "&Datei");
  menuBar->Append(menuHelp, "&Hilfe");
  wxFrameBase::SetMenuBar(menuBar);

  // Main sizer
  auto *mainSizer = new wxBoxSizer(wxVERTICAL);

  // Title
  auto *title = new wxStaticText(this, wxID_ANY, "Wherigo Player");
  title->SetFont(title->GetFont().Bold().Scaled(2.0));
  mainSizer->Add(title, 0, wxALL | wxALIGN_CENTER, 20);

  // Open button
  m_openButton = new wxButton(this, ID_OpenCartridge, "Cartridge öffnen...");
  m_openButton->SetMinSize(wxSize(200, 40));
  mainSizer->Add(m_openButton, 0, wxALL | wxALIGN_CENTER, 10);

  // Info panel (initially hidden)
  m_infoPanel = new wxPanel(this);
  auto *infoSizer = new wxBoxSizer(wxVERTICAL);

  // Splash image
  m_splashImage = new wxStaticBitmap(m_infoPanel, wxID_ANY, wxNullBitmap);
  infoSizer->Add(m_splashImage, 0, wxALL | wxALIGN_CENTER, 10);

  // Cartridge name
  m_cartridgeName = new wxStaticText(m_infoPanel, wxID_ANY, "");
  m_cartridgeName->SetFont(m_cartridgeName->GetFont().Bold().Scaled(1.5));
  infoSizer->Add(m_cartridgeName, 0, wxALL | wxALIGN_CENTER, 5);

  // Author
  m_cartridgeAuthor = new wxStaticText(m_infoPanel, wxID_ANY, "");
  infoSizer->Add(m_cartridgeAuthor, 0, wxALL | wxALIGN_CENTER, 5);

  // Description
  m_cartridgeDesc = new wxHtmlWindow(m_infoPanel, wxID_ANY, wxDefaultPosition,
                                     wxSize(500, 200));
  m_cartridgeDesc->SetMinSize(wxSize(500, 200));
  infoSizer->Add(m_cartridgeDesc, 1, wxALL | wxEXPAND, 10);

  // Start button
  m_startButton = new wxButton(m_infoPanel, ID_StartGame, "Spiel starten");
  m_startButton->SetMinSize(wxSize(200, 50));
  m_startButton->SetFont(m_startButton->GetFont().Bold());
  infoSizer->Add(m_startButton, 0, wxALL | wxALIGN_CENTER, 20);

  m_infoPanel->SetSizer(infoSizer);
  m_infoPanel->Hide();

  mainSizer->Add(m_infoPanel, 1, wxALL | wxEXPAND, 10);

  SetSizer(mainSizer);

  // Status bar
  wxFrameBase::CreateStatusBar();
  wxFrameBase::SetStatusText("Bitte eine Cartridge öffnen");

  // Event bindings
  Bind(wxEVT_MENU, &cStartScreen::OnOpenCartridge, this, ID_OpenCartridge);
  Bind(wxEVT_MENU, &cStartScreen::OnExit, this, wxID_EXIT);
  Bind(wxEVT_MENU, &cStartScreen::OnAbout, this, wxID_ABOUT);
  Bind(wxEVT_BUTTON, &cStartScreen::OnOpenCartridge, this, ID_OpenCartridge);
  Bind(wxEVT_BUTTON, &cStartScreen::OnStartGame, this, ID_StartGame);

  CentreOnScreen();
}

void cStartScreen::OnOpenCartridge(wxCommandEvent &event) {
  wxFileDialog openFileDialog(this, "Cartridge öffnen", "", "",
                              "Wherigo Cartridge (*.gwc)|*.gwc",
                              wxFD_OPEN | wxFD_FILE_MUST_EXIST);

  if (openFileDialog.ShowModal() == wxID_CANCEL) {
    return;
  }

  const wxString filePath = openFileDialog.GetPath();
  wxFrameBase::SetStatusText("Lade Cartridge: " + filePath);

  // Vor dem Laden: Info-Panel zurücksetzen
  if (m_infoPanel) {
    if (m_cartridgeName)
      m_cartridgeName->SetLabel("");
    if (m_cartridgeAuthor)
      m_cartridgeAuthor->SetLabel("");
    if (m_cartridgeDesc)
      m_cartridgeDesc->SetPage("");
    if (m_splashImage)
      m_splashImage->SetBitmap(wxNullBitmap);
  }

  // ggf. alten GameScreen schließen
  if (m_gameFrame) {
    m_gameFrame->Destroy();
    m_gameFrame = nullptr;
  }

  // Load the cartridge via cApp
  if (wxGetApp().loadCartridge(filePath.ToStdString())) {
    m_cartridgeLoaded = true;
    showCartridgeInfo();
    wxFrameBase::SetStatusText("Cartridge geladen - bereit zum Starten");
  } else {
    wxMessageBox("Fehler beim Laden der Cartridge", "Fehler",
                 wxOK | wxICON_ERROR);
    wxFrameBase::SetStatusText("Fehler beim Laden");
  }
}

void cStartScreen::showCartridgeInfo() {
  auto *cartridge = wxGetApp().getCartridge();
  if (!cartridge)
    return;

  // Set cartridge info
  m_cartridgeName->SetLabel(wxString::FromUTF8(cartridge->cartridgeName()));
  m_cartridgeAuthor->SetLabel("von " + wxString::FromUTF8(cartridge->author()));
  const auto desc = wxString::FromUTF8(cartridge->cartridgeDesc());
  if (desc.Find("<") == wxNOT_FOUND) {
    wxString plain(desc);
    plain.Replace("\n", "<br/>");
    m_cartridgeDesc->SetPage("<p>" + plain + "</p>");
  } else {
    m_cartridgeDesc->SetPage(desc);
  }

  // Load splash screen
  if (const auto splash = cartridge->splashScreen()) {
    const auto data = splash->getData();
    if (!data.empty()) {
      wxMemoryInputStream stream(data.data(), data.size());
      if (wxImage image(stream); image.IsOk()) {
        // Scale if too large
        const int maxHeight = 200;
        if (int maxWidth = 300;
            image.GetWidth() > maxWidth || image.GetHeight() > maxHeight) {
          double scaleX = static_cast<double>(maxWidth) / image.GetWidth();
          double scaleY = static_cast<double>(maxHeight) / image.GetHeight();
          double scale = std::min(scaleX, scaleY);
          image.Rescale(static_cast<int>(image.GetWidth() * scale),
                        static_cast<int>(image.GetHeight() * scale),
                        wxIMAGE_QUALITY_HIGH);
        }
        m_splashImage->SetBitmap(wxBitmap(image));
      }
    }
  }

  // Show info panel
  m_infoPanel->Show();
  m_openButton->SetLabel("Andere Cartridge öffnen...");
  Layout();
}

void cStartScreen::OnStartGame(wxCommandEvent &event) {
  if (!m_cartridgeLoaded) {
    wxMessageBox("Bitte zuerst eine Cartridge laden", "Hinweis",
                 wxOK | wxICON_INFORMATION);
    return;
  }

  // Create game frame if not exists
  if (!m_gameFrame) {
    m_gameFrame = new cGameScreen(this);
    m_gameFrame->SetPosition(GetPosition());
    m_gameFrame->SetSize(GetSize());
  }

  // Hide start frame, show game
  Hide();
  m_gameFrame->Show();

  // Start the game (call OnStart and start engine)
  wxGetApp().startGame();
}

void cStartScreen::onGameClosed() {
  // Called when game frame is closed
  Show();
  wxFrameBase::SetStatusText("Spiel pausiert - Cartridge noch geladen");
}

void cStartScreen::OnExit(wxCommandEvent &event) {
  // Clean up game frame
  if (m_gameFrame) {
    m_gameFrame->Destroy();
    m_gameFrame = nullptr;
  }
  Close(true);
}

void cStartScreen::OnAbout(wxCommandEvent &event) {
  wxMessageBox("Wherigo Player\n\nEin Desktop-Player für "
               "Wherigo-Cartridges\n\nVersion 0.1",
               "Über Wherigo Player", wxOK | wxICON_INFORMATION);
}
