DC Database
DC Database

Documentation for this module may be created at Module:ComicsInfobox/Comic/doc

local Infobox = {}
 
----------------------------
-- Libraries of functions --
----------------------------
-- stands for High Frequency
local HF = require('Module:ComicsHF')
-- Parses invocation parameters, trims whitespace, and removes blanks
local getArgs = require('Dev:Arguments').getArgs
-- Common and centralized functions
local ComicsInfobox = require('Module:ComicsInfobox')
local MonthParse = require("Module:Month")
local L = require('Dev:List')
local lang = mw.language.new('en')

-----------------------
-- Libraries of data --
-----------------------
-- Data tables for common Staff contributors
local StaffNames = require( 'Module:StaffCorrection' )

-- Since this should only be evaluated once per pageview, it's now global
_G.vars = { Pagename = mw.title.getCurrentTitle().text }

---------------------
-- Local functions --
---------------------
local function invokeInt(funcName)
  -- This wrapper allows invocation of an internal function from a frame.
	return function (frame)
		local args = getArgs(frame, { trim = true, removeBlanks = true })
		return Infobox[funcName](args, vars)
	end
end

Infobox.HeadTitle = invokeInt('_deriveHeadTitle')
Infobox.Events = invokeInt('_EventCollate')
Infobox.Image1 = invokeInt('_PrimaryCover')
Infobox.Image2 = invokeInt('_TextlessCover')
Infobox.ComicTitle = invokeInt('_deriveTitle')
Infobox.DigitalTitle = invokeInt('_deriveTitleDigital')
Infobox.ReleaseDate = invokeInt('_releaseDate')
Infobox.PublicationDate = invokeInt('_publicationDate')

function Infobox._deriveHeadTitle( args, vars )
  local Title = mw.html.create('div'):addClass('comic-headtitle')
  local category = {}
  if not HF.isempty( args.HeadTitle ) then
    if string.lower( args.HeadTitle ) ~= 'none' then
       Title:tag('span'):addClass('comic-headtitle'):wikitext(args.HeadTitle):done()
     end
   end
  if not HF.isempty( args.StoryArc or args.StoryArc2 ) then
    local StoryArc = mw.html.create('div'):addClass('comic-subtitle')
    local ArcText = string.format('Part of the [['..'%s]]', args.StoryArc )
    table.insert( category, string.format( '[['..'Category:%s]]', args.StoryArc ))
    if not HF.isempty(args.StoryArc2) then
      ArcText = ArcText .. string.format(' and [['..'%s]] story arcs', args.StoryArc2 )
      table.insert( category, string.format( '[['..'Category:%s]]', args.StoryArc2 ))
    else
      ArcText = ArcText .. ' story arc'
    end
    StoryArc:wikitext(ArcText):done()
    Title:node( StoryArc )
  end
  if not HF.isempty( args.Event or args.Event2 ) then
    local Event = mw.html.create('div'):addClass('comic-subtitle')
    local EventText = string.format('Part of the [['..'%s]]', args.Event )
    if not HF.isempty(args.Event2) then
      EventText = EventText .. string.format(' and [['..'%s]] events', args.Event2 )
    else
      EventText = EventText .. ' event'
    end
    Event:wikitext(EventText):done()
    Title:node( Event )
  end
  if not HF.isempty( args.Storyline ) then
    local Storyline = mw.html.create('div'):addClass('comic-subtitle')
      :wikitext(string.format('Part of the [[%s]] storyline.', args.Storyline )):done()
    table.insert( category, string.format( '[['..'Category'..':%s]]', args.Storyline ))
    Title:node( Storyline )
  end
  Title:tag('div'):addClass('comic-subtitle'):tag('br', { selfClosing = true }):done()
  return tostring(Title) .. table.concat( category )
end

function Infobox._EventCollate( args, vars )
    if not HF.isempty( args.Event or args.Event2 or args.Event3 ) then
        local EventText = string.format('Part of the [['..'%s]]', args.Event )
        if not HF.isempty(args.Event2) and HF.isempty(args.Event3) then
            EventText = EventText .. string.format(' and [['..'%s]] events',
                args.Event2 )
        elseif not HF.isempty(args.Event2) and not HF.isempty(args.Event3) then
            EventText = EventText .. string.format(',  [['..'%s]], and [['..'%s]] events',
                args.Event2, args.Event3 )
        else
            EventText = EventText .. ' event'
        end
    end
end

function Infobox._StoryCollate( args, vars )
        
end

function Infobox._PrimaryCover( args, vars )
  local givenImage = args.Image or args[1] or nil
  local fromPage = vars.Pagename .. '.jpg'
  local label = args.ImageText or args[2] or 'Cover'
  if givenImage and mw.title.new( givenImage, 'File' ).exists == true then
    return givenImage .. '|' .. label
  elseif fromPage and mw.title.new( fromPage, 'File' ).exists == true then
    return fromPage .. '|' .. label
  elseif givenImage then
      return givenImage .. '|' .. label
  else
      return nil
  end
end

function Infobox._TextlessCover( args, vars )
  local givenImage = args.Image2 or args[1] or nil
  local fromPage = vars.Pagename .. ' Textless.jpg'
  local label = args.Image2Text or args[2] or 'Textless'
  if givenImage and mw.title.new( givenImage, 'File' ).exists == true then
    return givenImage .. '|' .. label
  elseif fromPage and mw.title.new( fromPage, 'File' ).exists == true then
    return fromPage .. '|' .. label
  elseif givenImage then
      return givenImage .. '| '  .. label
      else
          return nil
  end
end

function Infobox._deriveTitle( args, vars )
  local Title, Volume, Issue  = string.match( vars.Pagename, "(.*)%s*Vol%s*(%d)%s*(%d*)")
   Title = args.Title or Title or nil
   Volume = args.Volume or Volume or nil
   Issue = args.Issue or Issue or nil
   if Title and Volume and Issue then
       return string.format('[[%s'..' Vol %s]] # %s', Title, Volume, Issue)
   elseif Title and Volume then
       return string.format('[[%s'..' Vol %s|%s]]', Title, Volume, Title)
   else
       return ''
   end
   
  end
  
function Infobox._deriveTitleDigital( args, vars )
  local Title, Volume, Chapter  = string.match( vars.Pagename, "(.*)%s*Vol%s*(%d)%s*(%d*)%s*%(Digital%)")
   Title = args.Title or Title or nil
   Volume = args.Volume or Volume or nil
   Chapter = args.Chapter or Chapter or nil
   if Title and Volume and Chapter then
       return string.format('[[%s'..' Vol %s]] # %s', Title, Volume, Chapter)
   elseif Title and Volume then
       return string.format('[[%s'..' Vol %s|%s]]', Title, Volume, Title)
   else
       return ''
   end
   
  end
function Infobox._releaseDate( args, vars )
    local ReleaseDate = args.ReleaseDate or nil
    local Date, Week, Year, CategoryTitle
    if not ReleaseDate then return '' end

    if string.match(ReleaseDate, 'Week') then
        Week, Year = string.match( ReleaseDate, "Week (.*),%s*(.*)")
        Week = tonumber(Week) - 3
        Date = lang:formatDate( 'F j, Y', Year..'-W'..Week )
    else
        Week = lang:formatDate( 'W', ReleaseDate)
        Year = lang:formatDate( 'Y', ReleaseDate)
        Date = lang:formatDate( 'F j, Y', ReleaseDate)
    end

    CategoryTitle = string.format('Category:Week %s, %s', Week, Year)

    if mw.title.new( CategoryTitle ) then
        return string.format('[[:%s|%s]]', CategoryTitle, Date)
    else
        return Date
    end
end

function Infobox._publicationDate( args, vars )
	local links = {}
    local Month, Year = args.Month or nil, args.Year or nil
	local gMonth = args.Month -- The given month input
	local Season = args.Season or nil
	
	if Month then
		if string.find( gMonth, 'Late' ) then
			Month = string.match( gMonth, "Late (.*)" )
		elseif string.find( gMonth, 'Early' ) then
			Month = string.match( gMonth, "Early (.*)" )
		elseif string.find( gMonth, 'Mid' ) then
			Month = string.match( gMonth, "Mid (.*)" )
		elseif string.find( gMonth, 'x' ) then
			Month = string.match( gMonth, "(.*)x" )
		else
	        Month = MonthParse._month( { gMonth } )
	    end

	    table.insert( links,
	        string.format( '[[:'..'Category:%s, %s|%s]]', Year, Month, Month )
	    )
	    table.insert( links, ', ' )
    end
    
    if Season then
        local ParsedSeason = MonthParse._month( Season )
        table.insert( links,
            string.format( '[[:'..'Category:%s, %s|%s]]', Year, ParsedSeason, PasedSeason )
        )
        table.insert( links, ', ' )
    end
    
    table.insert( links,
		string.format( '[[:'..'Category:%s|%s]]', Year, Year )
	)

	return table.concat( links )
end

Infobox.CreditCheck = invokeInt('_CreditCheck')
Infobox.ContributorLink = invokeInt('_ContributorLink')
Infobox.Contributors = invokeInt('_Contributors')
Infobox.UContributors = invokeInt('_UContributors')
Infobox.StoryTitleHeader = invokeInt('_StoryTitleHeader')
Infobox.PreviousIssue = invokeInt('_PreviousIssue')
Infobox.NextIssue = invokeInt('_NextIssue')

function Infobox._CreditCheck( parameters )
    if string.match( parameters[1], 'redited') or
      string.match( parameters[1], 'NA') or
      string.match( string.lower(parameters[1]), 'N/A') then
        return 'Uncredited'
    elseif parameters[2] then --Cancelation
        return ''
    elseif not parameters[2] then
        return Infobox._ContributorLink( 
			            { parameters[1],
			                role = parameters.role,
			                nocorrect = parameters.nocorrection }
			             )
    end
end

function Infobox._ContributorLink( args )
    local output = {}
    local role = args.role or args[2] or nil
    local correction
	table.insert( output, StaffNames:link( args[1] ) )
	if role then 
	    table.insert( output, StaffNames:cat_role( args[1], role ) ) 
	end
	return table.concat( output )
end

function Infobox._Contributors( parameters )
    -- This is a magical function that takes anywhere from 1 to infinite
    -- parameters and cuts them down to size. It makes links for contributors.
	local field = {
	    -- If parameters are numbered, where do the numbers start and end?
	    min = tonumber(parameters['Contributors.min']),
	    max = tonumber(parameters['Contributors.max']),
	    -- This can be "Writer" or "Writer1_"
	    prefix = parameters['Contributors.prefix'],
	    -- If it's specified that they contributed to certain pages...
	    pages = parameters['Contributors.pagesprefix'],
	    -- If the output is a list, what kind of list?
	    --- 'horizontal' (default), 'bulleted',
	    --- 'unbulleted' (aka <br/>),
	    --- 'ordered', or 'horizontal_ordered'
	    list = parameters['Contributors.list'] or 'horizontal',
	    role = parameters['Contributors.role'],
	    between = parameters['Contributors.between'],
	    nocreditcheck = parameters['Contributors.nocreditcheck'],
	    nocorrection = parameters['Contributors.nocorrection'],
	    canceled = parameters['Contributors.canceled'],
	    }
	local output = {}
	if field.min and field.max then
	    for i = field.min, field.max do
            local argcheck = field.prefix .. i
            local nextarg = field.prefix .. (i + 1)
            if field.pages then 
                pagestext = field.pages .. i
            end
            -- somewhere in here needs to be an assertion that the parameter you're looking for exists. Like "Writer" vs "Writer1_".
            if i == 1 and field.nocreditcheck ~= nil then
                Infobox._CreditCheck( { argcheck,
                    field.canceled,
			        role = field.role,
			        nocorrection = field.nocorrection 
                    })
            elseif i == 1 or parameters[argcheck] then
                local link = Infobox._ContributorLink(
			            { parameters[argcheck],
			                role = field.role,
			                nocorrect = field.nocorrection }
		            )
		        if pagestext and parameters[pagestext] then -- Value exists
			        link = link .. ('&#32;<small>(pg. '..parameters[pagestext]..')</small>')
			    end
                table.insert( output, link )
			end
			
			-- if parameters[nextarg] and field.between then
			--	table.insert( output, field.between )
			-- end
		end
	    -- return table.concat( output )
	    return L.makeList( 'horizontal' , output )
	else
	    -- A single parameter, huh?
	    -- We can just do a singleton.
	    local argcheck = field.prefix
	    if field.pages then pagestext = field.pages end
	    if field.nocreditcheck ~= nil then
                Infobox._CreditCheck( { argcheck,
                    field.canceled,
			        role = field.role,
			        nocorrection = field.nocorrection 
                    })
            elseif parameters[argcheck] then
                local link = Infobox._ContributorLink(
			            { parameters[argcheck],
			                role = field.role,
			                nocorrect = field.nocorrection }
		            )
		        if pagestext and parameters[pagestext] then -- Value exists
			        link = link .. ('&#32;<small>(pg. '..parameters[pagestext]..')</small>')
			    end
        end
	end
end

function Infobox._ContributorsDigital( parameters )
    -- This is a magical function that takes anywhere from 1 to infinite
    -- parameters and cuts them down to size. It makes links for contributors.
	local field = {
	    -- If parameters are numbered, where do the numbers start and end?
	    min = tonumber(parameters['Contributors.min']),
	    max = tonumber(parameters['Contributors.max']),
	    -- This can be "Writer" or "Writer1_"
	    prefix = parameters['Contributors.prefix'],
	    -- If it's specified that they contributed to certain pages...
	    pages = parameters['Contributors.pagesprefix'],
	    -- If the output is a list, what kind of list?
	    --- 'horizontal' (default), 'bulleted',
	    --- 'unbulleted' (aka <br/>),
	    --- 'ordered', or 'horizontal_ordered'
	    list = parameters['Contributors.list'] or 'horizontal',
	    role = parameters['Contributors.role'],
	    between = parameters['Contributors.between'],
	    nocreditcheck = parameters['Contributors.nocreditcheck'],
	    nocorrection = parameters['Contributors.nocorrection'],
	    canceled = parameters['Contributors.canceled'],
	    }
	local output = {}
	if field.min and field.max then
	    for i = field.min, field.max do
            local argcheck = field.prefix .. i
            local nextarg = field.prefix .. (i + 1)
            if field.pages then 
                pagestext = field.pages .. i
            end
            -- somewhere in here needs to be an assertion that the parameter you're looking for exists. Like "Writer" vs "Writer1_".
            if i == 1 and field.nocreditcheck ~= nil then
                Infobox._CreditCheck( { argcheck,
                    field.canceled,
			        role = field.role,
			        nocorrection = field.nocorrection 
                    })
            elseif i == 1 or parameters[argcheck] then
                local link = Infobox._ContributorLink(
			            { parameters[argcheck],
			                role = field.role,
			                nocorrect = field.nocorrection }
		            )
		        if pagestext and parameters[pagestext] then -- Value exists
			        link = link .. ('&#32;<small>(pg. '..parameters[pagestext]..')</small>')
			    end
                table.insert( output, link )
			end
			
			-- if parameters[nextarg] and field.between then
			--	table.insert( output, field.between )
			-- end
		end
	    -- return table.concat( output )
	    return L.makeList( 'horizontal' , output )
	else
	    -- A single parameter, huh?
	    -- We can just do a singleton.
	    local argcheck = field.prefix
	    if field.pages then pagestext = field.pages end
	    if field.nocreditcheck ~= nil then
                Infobox._CreditCheck( { argcheck,
                    field.canceled,
			        role = field.role,
			        nocorrection = field.nocorrection 
                    })
            elseif parameters[argcheck] then
                local link = Infobox._ContributorLink(
			            { parameters[argcheck],
			                role = field.role,
			                nocorrect = field.nocorrection }
		            )
		        if pagestext and parameters[pagestext] then -- Value exists
			        link = link .. ('&#32;<small>(pg. '..parameters[pagestext]..')</small>')
			    end
        end
	end
end

function Infobox._StoryTitleHeader( args )
-- if " then [[{{FULLPAGENAME}}#Appearing in {{{StoryTitle1}}}|{{{StoryTitle1}}}]]
-- if!" then "[[{{FULLPAGENAME}}#Appearing in "{{{StoryTitle1}}}"|{{{StoryTitle1}}}]]"
    if args[1] then
        local story = args[1]
        if string.match( story, '"') then 
            return string.format( '[[%s#Appearing in %s|%s]]',
            mw.title.getCurrentTitle().prefixedText, story, story )
        else
            return string.format( '[[%s#Appearing in %s|"%s"]]',
            mw.title.getCurrentTitle().prefixedText, string.format( '"%s"', story ), story )
        end
        
    else
        return '&nbsp;'
    end
    
end

function Infobox._PreviousIssue( args )
    local Title, Volume, Issue
    if args.PreviousIssue then
        Title, Volume, Issue  = string.match( PreviousIssue, "(.*)%s*Vol%s*(%d)%s*(%d*)")
    else
        Title, Volume, Issue  = string.match( vars.Pagename, "(.*)%s*Vol%s*(%d)%s*(%d*)")
    end
    
   Title = args.Title or Title or nil
   OneShot = args.OneShot or OneShot or nil
   Volume = tonumber(args.Volume) or tonumber(Volume) or nil
   Issue = tonumber(args.Issue) or tonumber(Issue) or nil
   
   if (Volume == 1 and Issue == 1) or (Volume == nil and Issue == nil) or OneShot ~= nil then
       -- new title, no previous
       return ''
   elseif Issue > 1 and Volume ~= 1 then
       -- same volume, new issue
       Issue = Issue - 1
       return string.format('[[%s Vol %s %s|%s Vol %s # %s]]', Title, Volume, Issue, Title, Volume, Issue )
   elseif Issue > 1 and Volume == 1 then
       -- same first volume, new issue
       Issue = Issue - 1
       return string.format('[[%s Vol %s %s|%s # %s]]', Title, Volume, Issue, Title, Issue )
   else
       -- no other use cases
       return ''
   end
end

function Infobox._NextIssue( args )
    local Title, Volume, Issue
    if args.NextIssue then
        Title, Volume, Issue  = string.match( NextIssue, "(.*)%s*Vol%s*(%d)%s*(%d*)")
    else
        Title, Volume, Issue  = string.match( vars.Pagename, "(.*)%s*Vol%s*(%d)%s*(%d*)")
    end
    
   Title = args.Title or Title or nil
   Volume = tonumber(args.Volume) or tonumber(Volume) or nil
   Issue = tonumber(args.Issue) or tonumber(Issue) or nil
   
   if Volume == nil and Issue == nil then
       -- new title, no previous
       return ''
   else
    NextIssue = string.format('%s Vol %s %s', Title, Volume, Issue + 1 )
    NextVolume = string.format('%s Vol %s', Title, Volume + 1 )
   end
   
   if mw.title.new( NextIssue ).exists == true then
       if Volume == 1 then 
           return string.format('[['..'%s|%s # %s]]', NextIssue, Title, Issue + 1)
       else 
           return string.format('[['..'%s|%s Vol %s # %s]]', NextIssue, Title, Volume, Issue + 1)
       end
   else
       return ''
   end
end

return Infobox