local yesno = require('Module:Yesno')
local barBox = require('Module:Bar box')  
local lang = mw.getContentLanguage
local language = lang:getCode
local i18n = require('Module:Medical cases chart/i18n')[language]
assert(i18n, 'no chart translations to: ' .. mw.language.fetchLanguageName(language, 'ta'))
local monthAbbrs = {}
for i = 1, 12 do
monthAbbrs[i] = lang:formatDate('M', '2020-' .. ('%02d'):format(i))
end  
local p = {}  
function p._toggleButton(active, customtoggles, id, label)
local on = active and '' or ' mw-collapsed'
local off = active and ' mw-collapsed' or ''
local outString =
'<span id="mw-customcollapsible-' .. id .. '" ' ..
'>' .. label .. '</span>' ..
'<span id="mw-customcollapsible-' .. id .. '">' .. label .. '</span>'
return outString
end  
function p._yearToggleButton(year)
return p._toggleButton(year.l, ' mw-customtoggle-' .. year.year, year.year, year.year)
end  
function p._monthToggleButton(year, month)
local lmon, label = lang:lc(month.mon), month.mon
local id = (year or '') .. lmon
local customtoggles = ' mw-customtoggle-' .. id  
if month.s then
label = label .. '&nbsp;' .. month.s -- "Mmm ##"
if month.s ~= month.e then -- "Mmm ##–##"
label = label .. '–' .. month.e
end
else
customtoggles = customtoggles .. (month.l and customtoggles .. month.l or '')
end  
for i, combination in ipairs(month.combinations) do
customtoggles = customtoggles .. ' mw-customtoggle-' .. combination -- up to 2 combinations per month so no need to table.concat
end  
return p._toggleButton(false, customtoggles, id, label)
end  
function p._lastXToggleButton(years, duration, combinationsL)
local months, id = years[#years].months, 'l' .. duration
local i, customtoggles = #months, {' mw-customtoggle-' .. id}  
if #years > 1 then
local year = years[#years].year
while months[i].l do
customtoggles[#customtoggles+1] = ' mw-customtoggle-' .. year .. lang:lc(months[i].mon) .. '-' .. id
if i == 1 then
if year == years[#years].year then
year = years[#years-1].year
months = years[#years-1].months
i = #months
else -- either first month is also lastX month or lastX spans more than 2 years, which is not intended yet
break
end
else
i = i - 1
end
end
else
while i > 0 and months[i].l do
customtoggles[#customtoggles+1] = ' mw-customtoggle-' .. lang:lc(months[i].mon) .. '-' .. id
i = i - 1
end
end  
for i, combinationL in ipairs(combinationsL) do
customtoggles[#customtoggles+1] = ' mw-customtoggle-' .. combinationL -- up to 3 combinationsL in 90 days
end  
return p._toggleButton(true, table.concat(customtoggles), id, mw.ustring.format(i18n.lastXDays, duration))
end  
function p._buildTogglesBar(dateList, duration, nooverlap)
local years = }
local months, combinationsL = years[1].months, {}  
local function addMonth(month)
if month.mon ~= months[#months].mon then -- new month
if month.year ~= years[#years].year then -- new year
years[#years+1] = {year=month.year, months={}}
months = years[#years].months -- switch months list
end
months[#months+1] = {mon=month.mon, combinations={}}
end
end
for i = 2, #dateList do -- deduplicate years and months
if #dateList[i] == 0 then -- specific date
addMonth(dateList[i])
months[#months].l = months[#months].l or dateList[i].l -- so that both ...-mon and ...-mon-lX classes are created
elseif #dateList[i] == 1 then -- interval within month
addMonth(dateList[i][1])
months[#months].l = months[#months].l or dateList[i].l
else -- multimonth interval
for j, month in ipairs(dateList[i]) do
addMonth(month)
months[#months].combinations[#months[#months].combinations+1] = dateList[i].id
end
combinationsL[#combinationsL+1] = dateList[i].id:find('-l%d+$') and dateList[i].id
end
end  
if nooverlap then
local lastDate = dateList[#dateList]
months[#months].e = tonumber(os.date('%d', lastDate.nDate or lastDate.nEndDate or lastDate.nAltEndDate)) -- end of final month  
local i = #dateList
repeat
i = i - 1
until i == 0 or (dateList[i].mon or dateList[i][1].mon) ~= months[#months].mon
if i == 0 then -- start of first and final month
months[#months].s = tonumber(os.date('%d', dateList[1].nDate))
else
months[#months].s = 1
end
end  
years[#years].l = true -- to activate toggle and respective months bar  
local monthToggles, divs = {}, nil
if #years > 1 then
local yearToggles, monthsDivs = {}, {}
for i, year in ipairs(years) do
yearToggles[#yearToggles+1] = p._yearToggleButton(year)
monthToggles = {}
months = year.months
for j, month in ipairs(months) do
monthToggles[#monthToggles+1] = p._monthToggleButton(year.year, month)
end
monthsDivs[#monthsDivs+1] =
'<div id="mw-customcollapsible-' .. year.year .. '">' .. table.concat(monthToggles) .. '</div>'
end
divs = '<div>' .. table.concat(yearToggles) .. '</div>' .. table.concat(monthsDivs)
else
for i, month in ipairs(months) do
monthToggles[#monthToggles+1] = p._monthToggleButton(nil, month)
end
divs = '<div>' .. table.concat(monthToggles) .. '</div>'
end
divs = divs .. '<div>' .. p._lastXToggleButton(years, duration, combinationsL) .. '</div>'
return '<div>' .. divs .. '</div>'
end  
p._barColors = {
'#A50026', --deaths
'SkyBlue', --recoveries
'Tomato', --cases or altlbl1
'Gold', --altlbl2
'OrangeRed' --altlbl3
}  
function p._customBarStacked(args)
local barargs = {}  
barargs[1] = args[1]  
local function _numwidth(i)
local nw = args.numwidth:sub(i, i)
if nw == 'n' then
return 0
elseif nw == 't' then
return 2.45
elseif nw == 'm' or nw == 'd' then
return 3.5
elseif nw == 'w' then
return 4.55
elseif nw == 'x' then
return 5.6
end
end  
barargs[2] =
'<span>' .. (args[7] or '') .. '</span>' ..
'<span>' .. (args[8] or '') .. '</span>'  
if #args.numwidth == 4 then
local pad = args.numwidth:sub(3, 3) == 'n' and '0' or '0.3em'
barargs.note2 =
'<span>' .. (args[9] or '') .. '</span>' ..
'<span>' .. (args[10] or '') .. '</span>'
end  
for i = 1, 5 do
barargs[2*i + 1] = p._barColors[i]
barargs[2*i + 2] = args[i+1] / args.divisor
barargs['title' .. i] = args[i+1]
end  
barargs.
barargs.collapsed = args.collapsed
barargs.id = args.id
barargs.rowstyle = args.rowheight and 'line-height:'.. args.rowheight ..';'  
return barBox._stacked(barargs)
end  
function p._row(args)
local barargs = {}  
barargs[1] = (args[1] or '⋮') .. (args.note0 or '')
barargs[2] = args[2] or 0
barargs[3] = args[3] or 0  
if args['alttot1'] then
barargs[4] = args['alttot1']
elseif args[4] then
barargs[4] = (args[4] or 0) - (barargs[2] or 0) - (barargs[3] or 0)
else
barargs[4] = 0
end  
barargs[5] = args[5] or 0  
if args['alttot2'] then
barargs[6] = args['alttot2']
elseif args[6] then
barargs[6] = (args[6] or 0) - (barargs[2] or 0) - (barargs[3] or 0)
else
barargs[6] = 0
end  
barargs[7] = args[7]  
local function changeArg(firstright, valuecol, changecol)
local change = ''
if args['firstright' .. firstright] then
change = '(' .. i18n.na .. ')'
elseif not args[1] and args[valuecol] then
change = '(=)'
else
change = args[changecol] and '(' .. args[changecol] .. ')' or ''
end
change = change .. (args['note' .. firstright] or '')  
return change
end  
barargs[8] = changeArg(1, 7, 8)
barargs[9] = args[9]
barargs[10] = changeArg(2, 9, 10)  
barargs.divisor = args.divisor
barargs.numwidth = args.numwidth
barargs.rowheight = args.rowheight  
local dates
if args.collapsible then
local duration = args.duration
if args.daysToEnd >= duration then
barargs.collapsed = 'y'
else
barargs.collapsed = ''
end  
if args.nooverlap and args.daysToEnd < duration then
barargs.id = 'l' .. duration
elseif args.nDate then
dates = {year=tonumber(os.date('%Y', args.nDate)), mon=lang:formatDate('M', os.date('%Y-%m', args.nDate)),
l=args.daysToEnd < duration and '-l' .. duration, nDate=args.nDate}
barargs.id = (args.multiyear and dates.year or *) .. lang:lc(dates.mon) .. (dates.l or *)
else
local id, y, m, ey, em = {},
tonumber(os.date('%Y', args.nStartDate or args.nAltStartDate)),
tonumber(os.date('%m', args.nStartDate or args.nAltStartDate)),
tonumber(os.date('%Y', args.nEndDate or args.nAltEndDate )),
tonumber(os.date('%m', args.nEndDate or args.nAltEndDate ))