// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#include "seed_phrase.h"

#include <cctype>

namespace dragonx {
namespace util {

std::string normalizeSeedPhrase(const std::string& raw)
{
    // Unicode whitespace encoded as UTF-8, each mapped to a single ASCII space; and zero-width marks
    // to strip. We substitute only these EXACT byte sequences, so ordinary (ASCII) word bytes are
    // never touched — the common all-ASCII phrase just gets its spacing collapsed and trimmed.
    static const char* const kSpaces[] = {
        "\xC2\xA0",                                                            // U+00A0 NBSP
        "\xC2\x85",                                                            // U+0085 NEL
        "\xE1\x9A\x80",                                                        // U+1680 ogham space
        "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83",        // U+2000–2003
        "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87",        // U+2004–2007
        "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A",                        // U+2008–200A
        "\xE2\x80\xAF",                                                        // U+202F narrow NBSP
        "\xE2\x81\x9F",                                                        // U+205F math space
        "\xE3\x80\x80",                                                        // U+3000 ideographic
    };
    static const char* const kZeroWidth[] = {
        "\xE2\x80\x8B", "\xE2\x80\x8C", "\xE2\x80\x8D",                        // U+200B/C/D
        "\xEF\xBB\xBF",                                                        // U+FEFF BOM / ZWNBSP
    };

    std::string s = raw;
    auto replaceAll = [&s](const std::string& from, const std::string& to) {
        if (from.empty()) return;
        std::size_t pos = 0;
        while ((pos = s.find(from, pos)) != std::string::npos) {
            s.replace(pos, from.size(), to);
            pos += to.size();
        }
    };
    for (const char* zw : kZeroWidth) replaceAll(zw, "");
    for (const char* sp : kSpaces)    replaceAll(sp, " ");

    // Collapse ASCII whitespace runs to a single space and trim ends.
    std::string out;
    out.reserve(s.size());
    bool pendingSpace = false;
    bool sawWord = false;
    for (unsigned char c : s) {
        if (std::isspace(c)) { pendingSpace = sawWord; continue; }
        if (pendingSpace) { out.push_back(' '); pendingSpace = false; }
        out.push_back(static_cast<char>(c));
        sawWord = true;
    }
    return out;
}

int seedPhraseWordCount(const std::string& phrase)
{
    int words = 0;
    bool inWord = false;
    for (unsigned char c : phrase) {
        const bool space = std::isspace(c) != 0;
        if (space) inWord = false;
        else if (!inWord) { inWord = true; ++words; }
    }
    return words;
}

bool isCompleteRecoveryPhrase(int words)
{
    return words == 24;
}

}  // namespace util
}  // namespace dragonx
