-- utf8_utils.lua
-- Минимальный набор UTF-8 функций для WoW (Lua 5.1)

local utf8_utils = {}

-- Подсчёт количества символов
function utf8_utils.len(s)
  local _, count = s:gsub("[^\128-\191]", "")
  return count
end

-- Подстрока по символам (i..j)
function utf8_utils.sub(s, i, j)
  i = i or 1
  j = j or -1
  local t, idx = {}, 0
  for uchar in s:gmatch("[%z\1-\127\194-\244][\128-\191]*") do
    idx = idx + 1
    if idx >= i and (j < 0 or idx <= j) then
      table.insert(t, uchar)
    end
  end
  return table.concat(t)
end

-- Удалить N последних символов
function utf8_utils.remove_last(s, n)
  local len = utf8_utils.len(s)
  return utf8_utils.sub(s, 1, len - n)
end

-- Капитализация первой буквы
function utf8_utils.capitalize(s)
  if not s or s == "" then return s end
  local first = utf8_utils.sub(s, 1, 1)
  local rest  = utf8_utils.sub(s, 2)
  return string.upper(first) .. rest
end

-- Итератор по кодам символов (как utf8.codes в Lua 5.3)
function utf8_utils.codes(s)
  local i = 1
  local len = #s
  return function()
    if i > len then return nil end
    local c = s:byte(i)

    local codepoint, size
    if c < 0x80 then
      codepoint, size = c, 1
    elseif c < 0xE0 then
      local c2 = s:byte(i+1)
      codepoint = (c - 0xC0) * 0x40 + (c2 - 0x80)
      size = 2
    elseif c < 0xF0 then
      local c2, c3 = s:byte(i+1), s:byte(i+2)
      codepoint = (c - 0xE0) * 0x1000 + (c2 - 0x80) * 0x40 + (c3 - 0x80)
      size = 3
    else
      local c2, c3, c4 = s:byte(i+1), s:byte(i+2), s:byte(i+3)
      codepoint = (c - 0xF0) * 0x40000 + (c2 - 0x80) * 0x1000 + (c3 - 0x80) * 0x40 + (c4 - 0x80)
      size = 4
    end

    local start = i
    i = i + size
    return start, codepoint
  end
end

-- Создание символа по коду (как utf8.char)
function utf8_utils.char(code)
  if code <= 0x7F then
    return string.char(code)
  elseif code <= 0x7FF then
    local b1 = 0xC0 + math.floor(code / 0x40)
    local b2 = 0x80 + (code % 0x40)
    return string.char(b1, b2)
  elseif code <= 0xFFFF then
    local b1 = 0xE0 + math.floor(code / 0x1000)
    local b2 = 0x80 + (math.floor(code / 0x40) % 0x40)
    local b3 = 0x80 + (code % 0x40)
    return string.char(b1, b2, b3)
  elseif code <= 0x10FFFF then
    local b1 = 0xF0 + math.floor(code / 0x40000)
    local b2 = 0x80 + (math.floor(code / 0x1000) % 0x40)
    local b3 = 0x80 + (math.floor(code / 0x40) % 0x40)
    local b4 = 0x80 + (code % 0x40)
    return string.char(b1, b2, b3, b4)
  end
  return ""
end

-- Экспортируем в глобал
_G.utf8_utils = utf8_utils