Documentation for this module may be created at Module:Infobox user/doc

local exports = {}

local known_services = {
  bluesky=true,
  carrd=true,
  deviantart=true,
  discord=true,
  facebook=true,
  github=true,
  gitlab=true,
  instagram=true,
  line=true,
  linkedin=true,
  linktree=true,
  mastodon=true,
  medium=true,
  notion=true,
  pinterest=true,
  pixiv=true,
  quora=true,
  reddit=true,
  roblox=true,
  scratch=true,
  skype=true,
  snapchat=true,
  stackexchange=true,
  stackoverflow=true,
  substack=true,
  telegram=true,
  threads=true,
  tiktok=true,
  tumblr=true,
  twitch=true,
  twitter=true,
  viber=true,
  wechat=true,
  whatsapp=true,
  x=true,
  youtube=true,
}

-- Debug me as `=p.main({ ["key"]="value" })` in the debug console.
function exports.main(frame)
  local args
  if frame == mw.getCurrentFrame() then
    args = frame:getParent().args
  else
    args = frame
  end

  -- Sorts the given keys.
  local sorted_keys = {}
  for key, _ in pairs(args) do
    table.insert(sorted_keys, key)
  end
  table.sort(sorted_keys)

  -- Creates a `<table>`.
  local tableElement = mw.html.create('table')
  tableElement
    :css('float', 'right')
    :css('text-align', 'left')

  -- Category names to be added
  local categories = {}

  for _, key in ipairs(sorted_keys) do
    local value = args[key]

    -- Key text to be output
    local keyText = key:gsub('^%d+%s*', '', 1)

    local lowerKey = string.lower(keyText)

    -- Value text to be output
    local valueText

    local specialValuePattern = '^__(%w+)__%s*'
    local _, _, specialValue = value:find(specialValuePattern)
    if specialValue ~= nil then
      valueText = value:gsub(specialValuePattern, '', 1)
    else
      valueText = value
    end

    -- Categorization
    if specialValue ~= 'NOCAT' then
      if specialValue == 'USER' or known_services[lowerKey] then
        table.insert(categories, string.format('%s users', lowerKey))
      elseif not value:find('https?://') and not value:find('^%p') then
        local lowerValue = string.lower(valueText)
        table.insert(categories, string.format('%s %s', lowerKey, lowerValue))
      end
    end

    tableElement
      :tag('tr')
        :tag('th')
          :wikitext(keyText)
          :done()
        :tag('td')
          :wikitext(valueText)
          :done()
        :done()
  end

  returnValue = tostring(tableElement)
  for _, category in ipairs(categories) do
    returnValue = returnValue .. string.format('\n[[Category:%s]]', category)
  end

  return returnValue
end

return exports