#include "lua/media_manager.h"

extern "C" {
#include <lua.h>
#include <lauxlib.h>
}

#include <wx/log.h>

namespace wherigo {

MediaManager& MediaManager::getInstance() {
  static MediaManager instance;
  return instance;
}

void MediaManager::init(lua_State *L, cartridge::Cartridge *cartridge) {
  m_luaState = L;
  m_cartridge = cartridge;

  buildMediaIndex(L);

  wxLogDebug("MediaManager initialized with %zu media entries", m_nameToIndex.size());
}

void MediaManager::buildMediaIndex(lua_State *L) {
  m_nameToIndex.clear();

  if (!L || !m_cartridge) return;

  // Iterate through all globals to find ZMedia objects
  lua_getglobal(L, "_G");
  lua_pushnil(L);

  while (lua_next(L, -2) != 0) {
    if (lua_istable(L, -1)) {
      lua_getfield(L, -1, "ClassName");
      if (lua_isstring(L, -1) && strcmp(lua_tostring(L, -1), "ZMedia") == 0) {
        lua_pop(L, 1); // pop ClassName

        std::string name;
        int mediaIndex = -1;

        // Get the Name
        lua_getfield(L, -1, "Name");
        if (lua_isstring(L, -1)) {
          name = lua_tostring(L, -1);
        }
        lua_pop(L, 1); // pop Name

        // Get the MediaIndex (set by wherigo_ZMedia when the object was created)
        lua_getfield(L, -1, "MediaIndex");
        if (lua_isnumber(L, -1)) {
          mediaIndex = lua_tointeger(L, -1);
        }
        lua_pop(L, 1); // pop MediaIndex

        if (!name.empty() && mediaIndex > 0) {
          m_nameToIndex[name] = mediaIndex;
          wxLogDebug("Media '%s' -> index %d", name.c_str(), mediaIndex);
        }
      } else {
        lua_pop(L, 1); // pop ClassName
      }
    }
    lua_pop(L, 1); // pop value
  }
  lua_pop(L, 1); // pop _G
}

std::vector<uint8_t> MediaManager::getMediaByName(const std::string &name) {
  const auto it = m_nameToIndex.find(name);
  if (it == m_nameToIndex.end()) {
    wxLogWarning("Media not found: %s", name.c_str());
    return {};
  }

  return getMediaByIndex(it->second);
}

std::vector<uint8_t> MediaManager::getMediaByIndex(int index) {
  if (!m_cartridge) {
    wxLogError("MediaManager: No cartridge set");
    return {};
  }

  const auto media = m_cartridge->getMedia(index);
  if (!media) {
    wxLogWarning("Media index %d not found in cartridge", index);
    return {};
  }

  return media->getData();
}

} // namespace wherigo

