#include "core/locale/lang.h"

#include <fstream>  // for basic_ifstream, basic_istream, ifstream
#include <sstream>

#include "core/resources/asset.h"  // for Asset
#include "core/resources/resource_helper.h"

// Instancia única
Lang *Lang::instance = nullptr;

// Singleton API
void Lang::init() {
    Lang::instance = new Lang();
}

void Lang::destroy() {
    delete Lang::instance;
    Lang::instance = nullptr;
}

auto Lang::get() -> Lang * {
    return Lang::instance;
}

// Constructor
Lang::Lang() = default;

// Destructor
Lang::~Lang() = default;

// Inicializa los textos del juego en el idioma seleccionado
auto Lang::setLang(Code lang) -> bool {
    std::string file;

    switch (lang) {
        case Code::ES_ES:
            file = Asset::get()->get("es_ES.txt");
            break;

        case Code::EN_UK:
            file = Asset::get()->get("en_UK.txt");
            break;

        case Code::BA_BA:
            file = Asset::get()->get("ba_BA.txt");
            break;

        default:
            file = Asset::get()->get("en_UK.txt");
            break;
    }

    for (auto &mTextString : text_strings_) {
        mTextString = "";
    }

    // Lee el fichero via ResourceHelper (pack o filesystem)
    auto bytes = ResourceHelper::loadFile(file);
    if (bytes.empty()) {
        return false;
    }

    std::string content(reinterpret_cast<const char *>(bytes.data()), bytes.size());
    std::stringstream ss(content);
    std::string line;
    int index = 0;
    while (std::getline(ss, line)) {
        // Normaliza CRLF: en Windows els fitxers es llegeixen en binari i
        // getline només talla pel \n, deixant un \r residual que faria que les
        // línies en blanc no semblen buides (i sobreescriguen més enllà de
        // mTextStrings, corrompent el heap).
        if (!line.empty() && line.back() == '\r') {
            line.pop_back();
        }
        // Almacena solo las lineas que no empiezan por # o no esten vacias
        const bool test1 = line.substr(0, 1) != "#";
        const bool test2 = !line.empty();
        if (test1 && test2) {
            if (index >= MAX_TEXT_STRINGS) {
                break;
            }
            text_strings_[index] = line;
            index++;
        }
    }

    return true;
}

// Obtiene la cadena de texto del indice
auto Lang::getText(int index) -> std::string {
    return text_strings_[index];
}

// Devuelve el siguiente idioma del ciclo (wrap-around)
auto Lang::nextLanguage(Code c) -> Code {
    const int NEXT = (static_cast<int>(c) + 1) % MAX_LANGUAGES;
    return static_cast<Code>(NEXT);
}