local data = require('Module:Delete/data')

local z = {}

function extractAliases(item)
    allnames = {item['code']}
    for j, alias in ipairs(item['aliases']) do
        table.insert(allnames, alias)
    end
    return allnames
end

function extractShortDesc(item)
    if item['description'] then
        return item['description']:gsub('{', '{'):gsub('}', '}'):gsub('|', '|')
    else
        return ''
    end
end

function extractDeleteReason(item)
    return item['deletereason'] or item['criteria'] or ''
end

function shortDesc(frame, name)
    name = mw.text.trim(name):upper()
    wt = {}
    for i, item in ipairs(data) do
        if name == '' or #name == 1 and item['code']:sub(1, 1) == name or item['code'] == name then
            para = extractShortDesc(item)
            if para ~= '' then
                table.insert(wt, para)
            end
        end
    end
    if short then
        return table.concat(wt, '\n')
    else
        return frame:preprocess(table.concat(wt, '\n'))
    end
end

function z.shortDesc(frame)
    return shortDesc(frame, frame.args[1])
end

function z.reasons(frame)
    wt = {}
    for i, item in ipairs(data) do
        if item['code'] == 'G8' then
            -- 在提示選單隱藏G8
        else
            allnames = extractAliases(item)
            table.insert(wt, '<tr><td>' .. mw.text.listToText(allnames, '、', '或') .. '<td title="' .. extractShortDesc(item) .. '">' .. item['criteria'] .. '</td>')
        end
    end
    return '<table class="wikitable">' .. table.concat(wt) .. '</table>'
end

function clone(t)
    local n = {}
    for k, v in pairs(t) do
        if type(v) == type({}) then
            n[k] = clone(v)
        else
            n[k] = v
        end
    end
    setmetatable(n, getmetatable(t))
    return n
end

local title = mw.title.getCurrentTitle()

function z._input(args, options)
    options = options or {}
    -- precache
    local map = {}
    for i, item in ipairs(options.data or data) do
        map[item['code']:lower()] = i
        for j, alias in ipairs(item['aliases']) do
            map[alias:lower()] = i
        end
    end
    -- parse
    local i = 1
    local rows = {}
    while options.maxArgs and (i < options.maxArgs) or true do
        local arg = args[i]
        local item
        if arg and map[mw.text.trim(arg:lower())] then
            item = clone(data[map[mw.text.trim(arg:lower())]])

            checkfunc = item['check']
            if options.checkFunc and checkfunc then
                item['check'] = checkfunc(title)
            else
                item['check'] = nil
            end

            -- special case for F1/F5
            if options.checkFile and (item['code'] == 'F1' or item['code'] == 'F5') then
                i = i + 1
                local img
                if args[i] then
                    img = mw.text.trim(args[i])
                else
                    img = nil
                end
                local success, imgtitle
                if img and img ~= '' then
                    success, imgtitle = pcall(mw.title.new, img, 'Media')
                else
                    imgtitle = nil
                end
                if success and imgtitle then
                    item['imgLink'] = ':[[:File:' .. imgtitle.text .. ']]'
                else
                    item['imgLink'] = nil
                end
            end
        elseif arg and mw.text.trim(arg) ~= '' then
            item = {
                code = '',
                criteria = arg
            }
        else
            if not options.maxArgs or i > 20 then
                -- 防止無限迴圈
                break
            end
            item = {
                code = nil,
                criteria = nil
            }
        end
        
        arg = args['c' .. i]
        if options.parseCommit and arg and mw.text.trim(arg) ~= '' then
            item['commit'] = arg
        end
        table.insert(rows, item)

        i = i + 1
    end
    if #rows > 0 then
        return rows
    else
        return nil
    end
end

function z.input(frame)
    if frame.args.parent then
        args = frame:getParent().args
    else
        args = frame.args
    end
    local rows = z._input(args, {
        maxArgs = 10,
        checkFunc = true,
        checkFile = true,
        parseCommit = true
    })
    if not rows then
        return frame.args.deletelink and '' or '<span style="font-weight:bold;color:red;">(請填寫理由)</span>' .. (args.cat or args.cate or args.category or '[[Category:快速删除候选|错]]')
    elseif frame.args.reasoncode then
        return rows[1]['code'] or ''
    end
    local deletelinks = {}
    local outputs = {}
    local cat
    for _, item in ipairs(rows) do
        if item['code'] and item['code'] ~= '' then
            local rowsuffix = ''
            local rowsuffix2 = ''
            local deletesuffix = ''
            -- special case for F1/F5
            if item['code'] == 'F1' or item['code'] == 'F5' then
                if item['imgLink'] then
                    deletesuffix = item['imgLink']
                else
                    if item['check'] then
                        rowsuffix2 = '<br><span class="error">為方便管理員檢查,請加上保留檔案的名稱。</span>'
                    else
                        item['check'] = '為方便管理員檢查,請加上保留檔案的名稱。'
                    end
                end
            end
            -- special case for O1/G10 in user namespace, see Wikipedia:机器人/申请/Xiplus-abot/8
            if title.namespace == 2 and (item['code'] == 'O1' or item['code'] == 'G10') then
                rowsuffix2 = args.cat or args.cate or args.category or ('[[Category:O1快速删除候选]]')
            end
            
            if item['check'] then
                rowsuffix = '<br><span class="error">' .. item['check'] .. '</span>' .. (args.cat or args.cate or args.category or '[[Category:快速删除候选|错]]')
            else
                if frame.args.deletelink then
                    table.insert(deletelinks, '[[WP:CSD#' .. item['code'] .. '|' .. item['code'] .. ']]: ' .. extractDeleteReason(item) .. deletesuffix)
                end
                rowsuffix = args.cat or args.cate or args.category or ('[[Category:快速删除候选|' .. (item['category'] or '速') .. ']]')
            end
            table.insert(outputs, '* <strong><span id="speedy-delete-' .. item['code'] .. '" title="' .. extractShortDesc(item) .. '">' .. item['criteria'] .. '([[WP:CSD#' .. item['code'] .. '|CSD ' .. item['code'] .. ']]' .. deletesuffix .. ')' .. rowsuffix .. rowsuffix2 .. '</span></strong>')
        elseif item['code'] == '' then
            local arg = item['criteria']
            -- try to read it as a title
            local success, aTitle = mw.title.new(mw.text.trim(arg))
            cat = args.cat or args.cate or args.category or '[[Category:快速删除候选|速]]'
            if aTitle and aTitle.exists then
                if frame.args.deletelink then
                    table.insert(deletelinks, '[[:' .. arg .. ']]')
                end
                table.insert(outputs, '*<strong>' .. cat .. '[[:' .. arg .. ']]</strong>')
            else
                if frame.args.deletelink then
                    table.insert(deletelinks, arg)
                end
                arg = string.gsub(arg, '^([*:#]*)(.*)', '%1<strong>%2</strong>')
                table.insert(outputs, '*' .. cat .. arg)
            end
        end

        if item['commit'] then
            table.insert(outputs, '*' .. item['commit'])
        end
    end
    -- for use by Twinkle
    if frame.args.deletelink then
        return mw.text.trim(table.concat(deletelinks, ';'):gsub('。;', ';'):gsub('。:', ':'))
    else
        return mw.text.trim(table.concat(outputs, '\n'))
    end
end

return z