模組:Topic box colour

require('strict')

local overall_class_labels = {
    ['ft'] = { icon = 'Cscr-featuredtopic.svg', name = '特色话题' },
    ['fa'] = { icon = 'Symbol star.svg', name = '“特色级”话题' },
    ['a'] = { icon = 'Symbol a class.svg', name = '“甲级”话题' },
    ['gt'] = { icon = 'Support_cluster.svg', name = '优良话题' },
    ['ga'] = { icon = 'Symbol support vote.svg', name = '“优良级”话题' },
    ['b'] = { icon = 'Symbol b class.svg', name = '“乙级”话题' },
    ['c'] = { icon = 'Symbol c class.svg', name = '“丙级”话题' },
    ['start'] = { icon = 'Symbol start class.svg', name = '“初级”话题' },
    ['stub'] = { icon = 'Symbol stub class.svg', name = '“小作品级”话题' },
    ['no'] = { icon = 'Symbol unrelated.svg', name = '“无级别”话题' },
    ['unassessed'] = { icon = 'Symbol question.svg', name = '“未评级”话题' },
}

local item_classes = {
    ['fa'] = 'fa',
    ['fl'] = 'fa',
    ['a'] = 'a',
    ['al'] = 'a',
    ['ga'] = 'ga',
    ['b'] = 'b',
    ['bl'] = 'b',
    ['c'] = 'c',
    ['cl'] = 'c',
    ['start'] = 'start',
    ['list'] = 'start',
    ['stub'] = 'stub',
    ['sl'] = 'stub',
    ['needed'] = 'stub',
    ['unassessed'] = 'unassessed',
}

local rank_order = {
    'unassessed', 'stub', 'start', 'c', 'b', 'ga', 'a', 'fa'
}

local function get_item_class(str)
    local template = require('Module:Class/icon')._main
    for k, v in pairs(item_classes) do
        if mw.ustring.find(str, template { k }, nil, true) then
            return v
        end
    end
end

local function get_color(code)
    local color = mw.getCurrentFrame():expandTemplate { title = 'Class/colour', args = { code } }
    if color == 'transparent' then
        return color, color
    end
    return color .. '66', color .. '11'
end

local function get_overall_status(args)
    local data = args.lead .. '\n' .. args.body
    local items = mw.text.split(data, '\n', true)

    local count_all, count_ranked, count_by_ranks = 0, 0, {}

    -- 獲取總條目數
    for _, v in pairs(rank_order) do
        count_by_ranks[v] = 0
    end

    -- 獲取各級別條目數
    for _, v in ipairs(items) do
        local rank = get_item_class(v)
        if count_by_ranks[rank] ~= nil then
            count_by_ranks[rank] = count_by_ranks[rank] + 1
            count_ranked = count_ranked + 1
        end
        count_all = count_all + 1
    end

    -- 獲取整體評級
    local overall_class = nil
    for i, v in pairs(rank_order) do
        if count_by_ranks[v] > 0 then
            overall_class = v
            local sum = 0
            for j = 1, i do
                sum = sum + count_by_ranks[rank_order[j]]
            end
            if sum < count_ranked / 2 then
                overall_class = rank_order[i + 1]
            end
            break
        end
    end

    return overall_class, count_all
end

local p = {}

local getArgs = require('Module:Arguments').getArgs
local function makeInvokeFunc(funcName)
    return function(frame)
        local args = getArgs(frame)
        return p[funcName](args)
    end
end

p.main = makeInvokeFunc('_main')
function p._main(args)
    local anchors = {}
    if args.titles then
        anchors = mw.text.split(args.titles, '%s*,%s*')
    end
    local overall_class, count_all = args.class, args.count_all
    if overall_class == nil or count_all == nil then
        overall_class, count_all = get_overall_status(args)
    end
    local color_dark, color_light = get_color(overall_class)

    -- 標題·左欄
    local header_left = mw.html.create('div'):addClass('topic_box_colour_header_left')
    local header_left_items = {}
    if args.template then
        table.insert(header_left_items, '[[:Template:' .. args.template .. '|模板]]')
    end
    if args.category then
        table.insert(header_left_items, '[[:Category:' .. args.category .. '|分類]]')
    end
    if #header_left_items > 0 then
        local text = table.concat(header_left_items, '·')
        header_left:wikitext(text)
    end

    -- 標題·中欄
    local header_center = mw.html.create('div'):addClass('topic_box_colour_header_center')
    header_center:wikitext(args.lead)

    -- 標題·右欄
    local header_right = mw.html.create('div'):addClass('topic_box_colour_header_right')
    do
        local label = overall_class_labels[overall_class]
        local inner = tostring(count_all) .. '篇條目'
        if args.icon == 'yes' then
            inner = '[[File:' .. label.icon .. '|' .. label.name .. '|18px]] ' .. inner
        end
        header_right:wikitext(inner)
    end

    -- 標題
    local header = mw.html.create('div')
    header:addClass('topic_box_colour_header')
    header:css('background', color_dark)
    header:node(header_left)
    header:node(header_center)
    header:node(header_right)

    -- 內容
    local body = mw.html.create('div'):addClass('topic_box_colour_body'):css('background', color_light)
    do
        local inner = mw.getCurrentFrame():expandTemplate { title = 'div col', args = { colwidth = '20em' } } .. '\n'
        inner = inner .. args.body .. '\n'
        inner = inner .. mw.getCurrentFrame():expandTemplate { title = 'div col end' }
        body:wikitext(inner)
    end

    -- 總表
    local result = mw.html.create('div')
    result:addClass('toccolours'):addClass('topic_box_colour')
    for _, v in ipairs(anchors) do
        result:tag('span'):attr('id', v)
    end

    result:node(header)
    result:node(body)

    return mw.getCurrentFrame():extensionTag { name = 'templatestyles', args = { src = 'Template:Topic box colour/styles.css' } }
            .. tostring(result)
end

return p