--------------------------------------------------------------------------------
-- Enum

local enum_metatable = {
	__tostring = function (e)     return 'Enum:' .. e.name or 'Enum: no name' end,
	__concat   = function (a, b)  return tostring(a) .. tostring(b) end,
}

local function enum (t)
	local e = {}
	for _, v in ipairs(t) do
		e[v] = setmetatable({ name = v }, enum_metatable)
	end
	return e
end

--------------------------------------------------------------------------------
-- Unicode

local UNICODE_CHAR_PATTERN = '[\01-\127\192-\255][\128-\191]*'

local UNICODE_ZERO_WIDTH_CHARACTERS = {}
for i = 128, 191 do  UNICODE_ZERO_WIDTH_CHARACTERS['\204'..string.char(i)] = true  end
for i = 128, 175 do  UNICODE_ZERO_WIDTH_CHARACTERS['\205'..string.char(i)] = true  end

local function iterate_utf8_chars (str)
	-- TODO: Detect invalid codepoints.
	return str:gmatch(UNICODE_CHAR_PATTERN)
end

local function utf8_string_length (str)
	assert(type(str) == 'string')
	local len = 0
	for char in iterate_utf8_chars(str) do
		if not UNICODE_ZERO_WIDTH_CHARACTERS[char] then
			len = len + 1
		end
	end
	return len
end

--------------------------------------------------------------------------------
-- L utility

local function width_of_strings_in_l (l, start_i, stop_i)
    -- Argument fixing and Error Checking
    assert(type(l) == 'table')

    local start_i, stop_i = start_i or 1, stop_i or #l

    assert(type(start_i) == 'number')
    assert(type(stop_i)  == 'number')

    -- Do stuff
    local  width = 0
    for i = start_i, stop_i do
        local item_width = 0
        if type(l[i]) == 'string' then
            item_width = utf8_string_length(l[i])
        elseif l[i].est_width then
            item_width = l[i].est_width
        end
        width = width + item_width
    end

    -- Return
    return width
end



--------------------------------------------------------------------------------

return {
	TABLE_TYPE = enum { 'EMPTY', 'SEQUENCE', 'STRING_MAP', 'PURE_MAP', 'MIXED', 'SET' },
	DISPLAY = { HIDE = 1, SMALL = 2, INLINE = 3, EXPAND = 4 },

	utf8_string_length = utf8_string_length,
    width_of_strings_in_l = width_of_strings_in_l,
}