--[[
  @package    eg4-crank-ui-2
  @file       utf8-utils.lua
  @brief      UTF8 related utilities.
]]

local UTF8 = {}

---
--- @brief iterator for utf8 strings
--- @param value - utf8 string
--- @return iterator
function utf8_iter(value)
  local start = 1
  local pos1 = 1
  return function ()
    if pos1 == nil then return end
    start = start + 1
    local pos2 = utf8.offset(value, start)
    local c = value:sub(pos1, pos2 and (pos2 - 1))
    pos1 = pos2
    return c
  end
end

---
--- @brief  Converts utf8 string to uppercase
--- @param  self - utf8 string
--- @return uppercase string
function string:utf8_upper()
  local UPPER_MAP = UTF8.UPPER_MAP
  local result = ""
  for c in utf8_iter(self) do
    result = result .. (UPPER_MAP[c] and UPPER_MAP[c] or c)
  end
  return result:upper()
end

---
--- @brief  Converts utf8 string to lowercase
--- @param  self - utf8 string
--- @return lowercase string
function string:utf8_lower()
  local LOWER_MAP = UTF8.LOWER_MAP
  local result = ""
  for c in utf8_iter(self) do
    result = result .. (LOWER_MAP[c] and LOWER_MAP[c] or c)
  end
  return result:lower()
end

---
--- @brief  Remove accented characters from a string
--- @param  self - the string to remove accented characters from
--- @return the string with accented characters removed
function string:remove_accents()
  local result = ""
  for c in utf8_iter(self) do
    result = result..(UTF8.ACCENT_MAPPING[c] and UTF8.ACCENT_MAPPING[c] or c)
  end
  return result
end

---
--- @brief  Map for lower to uppercase UTF-8 characters
UTF8.UPPER_MAP = {
  ['à'] = 'À',
  ['á'] = 'Á',
  ['â'] = 'Â',
  ['ã'] = 'Ã',
  ['ä'] = 'Ä',
  ['å'] = 'Å',
  ['æ'] = 'Æ',
  ['ç'] = 'Ç',
  ['è'] = 'È',
  ['é'] = 'É',
  ['ê'] = 'Ê',
  ['ë'] = 'Ë',
  ['ì'] = 'Ì',
  ['í'] = 'Í',
  ['î'] = 'Î',
  ['ï'] = 'Ï',
  ['ð'] = 'Ð',
  ['ñ'] = 'Ñ',
  ['ò'] = 'Ò',
  ['ó'] = 'Ó',
  ['ô'] = 'Ô',
  ['õ'] = 'Õ',
  ['ö'] = 'Ö',
  ['ø'] = 'Ø',
  ['ù'] = 'Ù',
  ['ú'] = 'Ú',
  ['û'] = 'Û',
  ['ü'] = 'Ü',
  ['ý'] = 'Ý',
  ['þ'] = 'Þ',
  ['ā'] = 'Ā',
  ['ă'] = 'Ă',
  ['ą'] = 'Ą',
  ['ć'] = 'Ć',
  ['ĉ'] = 'Ĉ',
  ['ċ'] = 'Ċ',
  ['č'] = 'Č',
  ['ď'] = 'Ď',
  ['đ'] = 'Đ',
  ['ē'] = 'Ē',
  ['ĕ'] = 'Ĕ',
  ['ė'] = 'Ė',
  ['ę'] = 'Ę',
  ['ě'] = 'Ě',
  ['ĝ'] = 'Ĝ',
  ['ğ'] = 'Ğ',
  ['ġ'] = 'Ġ',
  ['ģ'] = 'Ģ',
  ['ĥ'] = 'Ĥ',
  ['ħ'] = 'Ħ',
  ['ĩ'] = 'Ĩ',
  ['ī'] = 'Ī',
  ['ĭ'] = 'Ĭ',
  ['į'] = 'Į',
  ['ı'] = 'İ',
  ['ĳ'] = 'Ĳ',
  ['ĵ'] = 'Ĵ',
  ['ķ'] = 'Ķ',
  ['ĺ'] = 'Ĺ',
  ['ļ'] = 'Ļ',
  ['ľ'] = 'Ľ',
  ['ŀ'] = 'Ŀ',
  ['ł'] = 'Ł',
  ['ń'] = 'Ń',
  ['ņ'] = 'Ņ',
  ['ň'] = 'Ň',
  ['ŋ'] = 'Ŋ',
  ['ō'] = 'Ō',
  ['ŏ'] = 'Ŏ',
  ['ő'] = 'Ő',
  ['œ'] = 'Œ',
  ['ŕ'] = 'Ŕ',
  ['ŗ'] = 'Ŗ',
  ['ř'] = 'Ř',
  ['ś'] = 'Ś',
  ['ŝ'] = 'Ŝ',
  ['ş'] = 'Ş',
  ['š'] = 'Š',
  ['ţ'] = 'Ţ',
  ['ť'] = 'Ť',
  ['ŧ'] = 'Ŧ',
  ['ũ'] = 'Ũ',
  ['ū'] = 'Ū',
  ['ŭ'] = 'Ŭ',
  ['ů'] = 'Ů',
  ['ű'] = 'Ű',
  ['ų'] = 'Ų',
  ['ŵ'] = 'Ŵ',
  ['ŷ'] = 'Ŷ',
  ['ÿ'] = 'Ÿ',
  ['ź'] = 'Ź',
  ['ż'] = 'Ż',
  ['ž'] = 'Ž',
  ['ſ'] = 'ſ',
  ['ƀ'] = 'Ɓ',
  ['ƃ'] = 'Ƃ',
  ['ƅ'] = 'Ƅ',
  ['ƈ'] = 'Ƈ',
  ['ƌ'] = 'Ƌ',
  ['ƒ'] = 'Ƒ',
  ['ƙ'] = 'Ƙ',
  ['ƣ'] = 'Ƣ',
  ['ơ'] = 'Ơ',
}

---
---  @brief  Creates a map of lowercase to uppercase characters
UTF8.LOWER_MAP = {}
for key, val in pairs(UTF8.UPPER_MAP) do
  UTF8.LOWER_MAP[val] = key
end

---
--- @brief  Create map of accent characters to their non-accented equivalent.
UTF8.ACCENT_MAPPING = {}
local accented_keys = require("controls/accented-key-mapping")
for k,v in pairs(accented_keys) do
  if v then
    for i = 1, #v do
      for j = 1, #v[i] do
        UTF8.ACCENT_MAPPING[v[i][j]] = k
      end
    end
  end
end
