Documentation for this module may be created at Module:Sandbox/LVL/doc

local p = {}

local iconDataRaw = mw.loadJsonData("Data:ResourceLookup.json")
local iconData2 = mw.loadJsonData("Data:ResourceLookup2.json")
local dictionary = mw.loadJsonData("Data:Dictionary")

local iconData = {}

for k, v in pairs(iconDataRaw) do
    iconData[k] = v
end

for k, v in pairs(iconData2) do
    iconData[k] = v
end

local lang_codes = mw.loadJsonData("Data:LangCodes.json")
local lang_module = require("Module:Lang")
local table_data = require("Module:Icon/data")

local cachedLangCode

local linkOverrides = table_data.linkOverrides
local legacyItems = table_data.legacyItems
local missingImageOverrides = table_data.missingImageOverrides
local aliases = table_data.aliases
local renames = table_data.renames

local function getLangCode()
    if cachedLangCode then
        return cachedLangCode
    end

    local title = mw.title.getCurrentTitle().fullText
    local subpageLang = title:match("/([^/]+)$")
    local langCode = (subpageLang and lang_codes[subpageLang]) and subpageLang or "en"

    cachedLangCode = langCode
    return langCode
end

-- Infer image path from name, with override support for missing images
local function getImage(iconInfo, args)
    local lowerName = iconInfo.name:lower()

    if args.image then
        return args.image
    end

    return missingImageOverrides[lowerName] or (iconInfo.name .. ".png")
end

-- Get the translated name (Moved up so getLink can use it)
local function getTranslatedName(iconInfo, langCode)
    if langCode == "en" then
        return iconInfo.name
    end

    -- 1. Direct key
    if iconInfo.key and iconInfo.key ~= "" then
        local translated = lang_module.get_string(iconInfo.key, langCode, iconInfo.name
        )

        if type(translated) == "string" then
            return (translated:gsub("<[^>]+>", ""))
        end

        return iconInfo.name
    end

    -- 2. Dictionary lookup
    if iconInfo.key_dictionary and iconInfo.key_dictionary ~= "" then
        local entry = dictionary[iconInfo.key_dictionary]

        if type(entry) == "table" then
            return entry[langCode]
                or entry.en
                or iconInfo.name
        end
    end

    -- No valid key > fallback
    return iconInfo.name
end

-- Infer link from type and available fields
local function getLink(iconInfo, langCode)
    if iconInfo.type == "ability" then
        local hero = iconInfo.hero_name or iconInfo.name
        
        -- Get the translated name for the specific ability
        local abilityName = getTranslatedName(iconInfo, langCode)
        
        -- Format for URL: replace spaces with underscores
        local anchor = abilityName:gsub(" ", "_")
        
        return hero .. "#" .. anchor
    end

    return linkOverrides[iconInfo.name] or iconInfo.name
end

-- Returns the canonical display name for a given user input
-- Used by templates to store the correct casing in data attributes
-- Normalizes casing so exact string matches work reliably in Lua modules
function p.getCanonicalName(frame)
    local name = frame.args[1] or ""
    local lowerName = name:lower()

    if renames[lowerName] then
        lowerName = renames[lowerName]
    elseif aliases[lowerName] then
        lowerName = aliases[lowerName]
    end

    local iconInfo = iconData[lowerName] or legacyItems[lowerName]

    -- If unknown, return original input
    if not iconInfo then
        return name
    end

	-- Quick hack: ability names are used by MediaWiki:Gadget-infobox-tooltip.js and expected to be localized
    local langCode = getLangCode()

    if iconInfo.type == "ability" then
        return getTranslatedName(iconInfo, langCode)
    end

    return iconInfo.name
end

local function render(name, args)
    local originalName = name
    local lowerName = name:lower()
    args = args or {}

    if renames[lowerName] then
        lowerName = renames[lowerName]
    elseif aliases[lowerName] then
        lowerName = aliases[lowerName]
    end

    -- Lookup live data > legacy fallback
    local iconInfo = iconData[lowerName] or legacyItems[lowerName]

    -- Throw error if not found
    if not iconInfo then
        return string.format("[[:Category:Module:Icon ERROR|Icon not found]] ('%s'). [[Category:Module:Icon ERROR]]", name)
    end

    local customText = args.l1 ~= "" and args.l1 or nil
    local customLink = args.link ~= "" and args.link or nil
    local size = args.size or "20px"
    local noLink = args["no-link"] == "true"
    local noFile = args["no-file"] == "true"
    local iconOnly = args["icon-only"] == "true"

    for k, v in pairs(args) do
        if type(k) == "number" and k > 1 then
            local val = mw.text.trim(v)
            if val == "icon-only" then
                iconOnly = true
            elseif val == "no-link" then
                noLink = true
            elseif val:match("^%d+px$") then
                size = val
            end
        end
    end

    local langCode = getLangCode()

    local displayName
    if customText then
        displayName = customText
    elseif renames[name:lower()] then
        -- Preserve original if renamed
        displayName = originalName
    else
        displayName = getTranslatedName(iconInfo, langCode)
    end

    local baseLink = customLink or getLink(iconInfo, langCode)
    local fragment = ""

    -- Split the fragment (#Abilities) from the base link
    if baseLink:find("#") then
        local parts = mw.text.split(baseLink, "#", true)
        baseLink = parts[1]
        fragment = "#" .. (parts[2] or "")
    end

    local link = baseLink

    if not customLink and langCode ~= "en" and baseLink ~= "" then
        link = baseLink .. "/" .. langCode
    end

    -- Reattach fragment at the end
    link = link .. fragment

    -- Add CSS class for abilities
    local style
    if iconInfo.type == "ability" then
        style = 'class="module-icon-ability" style="position:relative; bottom:2px;"'
    else
        style = 'class="c-icon" style="position:relative; bottom:2px;"'
    end

    local imageLink = noLink and "" or link
    local iconHtml = ""

    if not noFile then
        local image = getImage(iconInfo, args)
        iconHtml = string.format('<span %s>[[File:%s|%s|link=%s]]</span>', style, image, size, imageLink)
    end

    if iconOnly or displayName == "" then
        return iconHtml
    end

    local textHtml = (noLink or link == "") and displayName or string.format('[[%s|%s]]', link, displayName)

    if iconHtml ~= "" then
        return '<span style="white-space:nowrap;">' .. iconHtml .. " " .. textHtml .. '</span>'
    else
        return textHtml
    end
end

-- Template entrypoint
function p.render(frame)
    local args = frame:getParent().args
    local name = args[1] or ""

    return render(name, args)
end

-- Module entrypoint
function p._render(name, args)
    return render(name, args)
end

return p