# Module:Listen

local mFileLink = require('Module:File link')  
local mTableTools = require('Module:TableTools')  
local mSideBox = require('Module:Side box')  
local lang = mw.language.new('en')  

local p = {}  

local function formatLength(length)  
-- Formats a duration in seconds in "(h:)mm:ss" (minutes are zero-padded  
-- only if there are hours).  
if not length or length == 0 then  
return nil  
end  

-- Add 0.5 to offset the rounding down  
local t = lang:getDurationIntervals(length + 0.5, { 'hours', 'minutes', 'seconds' })  
local s = t.seconds and string.format('%02d', t.seconds) or '00'  
local m = t.minutes or 0  

local span = mw.html.create('span'):addClass('duration')  
if t.hours then  
span  
:tag('span')  
:addClass('h')  
:wikitext(t.hours)  
:done  
:wikitext(':')  
m = string.format('%02d', m)  
end  
span  
:tag('span')  
:addClass('min')  
:wikitext(m)  
:done  
:wikitext(':')  
:tag('span')  
:addClass('s')  
:wikitext(s)  
:done  
return tostring(span)  
end  

local function renderRow(filename, title, play, alt, description, start, length, hasImage)  
-- Renders the HTML for one file description row.  
if not filename then  
return nil  
end  

length = formatLength(length)  
length = length and string.format(' (%s)', length) or ''  

local root = mw.html.create('')  
root:tag('div')  
:addClass('haudio')  
:newline  
:tag('div')  
:addClass('listen-file-header')  
:wikitext(string.format(  
'%s',  
filename,  
title or '',  
length  
))  
:done  
:newline  
:tag('div')  
:wikitext(play ~= 'no' and mFileLink._main{  
file = filename,  
size = hasImage and * or *,  
alt = alt,  
start = start  
}  
or nil  
:done  
:newline  
:tag('div')  
:addClass('description')  
:wikitext(description)  
:done  
:done  
return tostring(root)  
end  

local function renderTrackingCategories(isPlain, hasMissing, isEmpty, titleObj)  
-- Renders all tracking categories produced by the template.  
-- isPlain, hasMissing and isEmpty are passed through from p._main,  
-- and the titleObj is only used for testing purposes.  
local cats = {}  
local currentTitle = titleObj or mw.title.getCurrentTitle  
if currentTitle.namespace == 0 then  
-- We are in mainspace.  
if not isEmpty then  
cats[#cats + 1] = 'Articles with hAudio microformats'  
end  
if hasMissing then  
cats[#cats + 1] = 'Articles with empty listen template'  
end  
end  
if isPlain then  
cats[#cats + 1] = 'Listen template using plain parameter'  
end  
for i, cat in ipairs(cats) do  
cats[i] = string.format('', cat)  
end  
return table.concat(cats)  
end  

function p._main(args)  
-- Organise the arguments by number.  
local isPlain = args.plain == 'yes'  
local isEmbedded = args.embed and true  
local hasImage = not isPlain and not isEmbedded and args.image ~= ''  

local numArgs, missingFiles = {}, {}  
do  
local origNumArgs = mTableTools.numData(args)  
origNumArgs[1] = origNumArgs.other -- Overwrite args.filename1 etc. with args.filename etc.  
origNumArgs = mTableTools.compressSparseArray(origNumArgs)  
for i, t in ipairs(origNumArgs) do  
-- Check if the files exist.  
local obj = t.filename and mw.title.makeTitle(-2, t.filename)  
if obj and obj.exists then  
if t.length == 'yes' or  
-- Show length if the video height would be less than  
obj.file.width / obj.file.height > (hasImage and 1.547 or 1.434)  
then  
t.length = obj.file.length  
else  
t.length = nil  
end  
numArgs[#numArgs + 1] = t  
else  
missingFiles[#missingFiles + 1] = t.filename or i  
end  
end  
end  

-- Render warning  
local hasMissing = #missingFiles ~= 0  
local previewWarning = ''  
if hasMissing then  
for i, v in ipairs(missingFiles) do  
missingFiles[i] = type(v) == 'string'  
and string.format('missing file "%s"', v)  
or string.format('empty filename #%s', v)  
end  
previewWarning = string.format(  
'Page using Template:Listen with %s',  
mw.text.listToText(missingFiles)  
previewWarning = require('Module:If preview')._warning({previewWarning})  
end  

-- Exit early if exist.  
if #numArgs == 0 then  
return previewWarning .. renderTrackingCategories(isPlain, hasMissing, true)  
end  

-- Build the arguments for  
local sbArgs = {  
metadata = 'no',  
position = (isPlain or isEmbedded) and '' or args.pos,  
style = args.style,  
templatestyles = 'Module:Listen/styles.css'  
}  

-- Class arguments  
do  
local class = {  
'listen',  
'noprint'  
}  
if isPlain then  
table.insert(class, 'listen-plain')  
end  
if isEmbedded then  
table.insert(class, 'listen-embedded')  
end  
if not hasImage then  
table.insert(class, 'listen-noimage')  
end  
if args.pos == '' and not isPlain and not isEmbedded then  
table.insert(class, 'listen-')  
elseif args.pos == '' then  
table.insert(class, 'listen-')  
end  

sbArgs.class = table.concat(class, ' ')  
end  

-- Image  
if not isPlain and not isEmbedded then  
if args.image then  
sbArgs.image = args.image  
else  
local images = {  
speech = 'Audio-input-microphone.svg',  
music = 'Gnome-mime-audio-openclipart.svg',  
default = 'Gnome-mime-sound-openclipart.svg'  
}  
sbArgs.image = mFileLink._main{  
file = args.type and images[args.type] or images.default,  
size = '65x50px',  
location = '',  
link = '',  
alt = ''  
}  
end  
end  

-- Text  
do  
local header  
if args.header then  
header = mw.html.create('div')  
header:addClass('listen-header')  
:wikitext(args.header)  
header = tostring(header) .. '\n'  
else  
header = ''  
end  
local text = {}  
for i, t in ipairs(numArgs) do  
text[#text + 1] = renderRow(  
t.filename, t.title, t.play, t.alt, t.description, t.start,  
t.length, hasImage  
if numArgs[i + 1] then  
text[#text + 1] = '<hr/>'  
end  
end  
sbArgs.text = header .. table.concat(text)  
end  

-- Below  
if not isPlain and not isEmbedded and args.help ~= 'no' then  
sbArgs.below = string.format(  
'<hr/><i>%s கேட்பதில் பிரச்சினையா? ஊடக உதவியைப் பார்க்கவும்.</i>',  
1. numArgs == 1 and 'இக்கோப்பைக்' or 'இக்கோப்புகளைக்'
end  

-- Render the side box.  
local sideBox = mSideBox._main(sbArgs)  

-- Render the tracking categories.  
local trackingCategories = renderTrackingCategories(isPlain, hasMissing)  

return previewWarning .. sideBox .. trackingCategories  
end  

function p.main  
local origArgs = :getParent.args  
local args = {}  
for k, v in pairs(origArgs) do  
if v ~= '' then  
args[k] = v  
end  
end  
return p._main(args)  
end  

return p