-- new features.

-- Process a numeric argument to make sure it is a positive
-- integer.
local function processNumArg( num )
 if num then
 num = tonumber( num )
 if type( num ) == 'number' then
 num = math.floor( num )
 if num >= 0 then
 return num
 end
 end
 end
 return nil
end

-- Checks whether a page exists, going through pcall
-- in case we are over the expensive function limit.
local function checkPageExists( title )
 if not title then
 error
 end
 local noError, titleObject = pcall
 if not noError then
 -- If we are over the expensive function limit then assume
 -- that the page doesn't exist.
 return false
 else
 if titleObject then
 return titleObject.exists
 else
 return false -- Return false if given a bad title.
 end
 end
end

-- Checks every nth archive to see if it exists, and returns the
-- number of the first archive that doesn't exist. It is
-- necessary to do this in batches because each check is an
-- expensive function call, and we want to avoid making too many
-- of them so as not to go over the expensive function limit.
local function checkArchives
 local i = start
 local exists = true
 while exists do
 exists = checkPageExists( prefix .. tostring( i ) )
 if exists then
 i = i + n
 end
 end
 return i
end

-- Return the biggest archive number, using checkArchives
-- and starting in intervals of 1000. This should get us a
-- maximum of 500,000 possible archives before we hit the
-- expensive function limit.
local function getBiggestArchiveNum
 -- Return the value for max if it is specified.
 max = processNumArg( max )
 if max then
 return max
 end
 
 -- Otherwise, detect the largest archive number.
 start = start or 1
 local check1000 = checkArchives
 if check1000 == start then
 return 0 -- Return 0 if no archives were found.
 end
 local check200 = checkArchives
 local check50 = checkArchives
 local check10 = checkArchives
 local check1 = checkArchives
 -- check1 is the first page that doesn't exist, so we want to
 -- subtract it by one to find the biggest existing archive.
 return check1 - 1
end

-- Get the archive link prefix (the title of the archive pages
-- minus the number).
local function getPrefix
 local ret = root or mw.title.getCurrentTitle.prefixedText
 ret = ret .. '/'
 if prefix then
 ret = ret .. prefix
 if prefixSpace == 'yes' then
 ret = ret .. ' '
 end
 else
 ret = ret .. 'Archive '
 end
 return ret
end

-- Get the number of archives to put on one line. Set to
-- math.huge if there should be no line breaks.
local function getLineNum
 local linksToNum = tonumber( links )
 local lineNum
 if nobr == 'yes' or (links and not linksToNum) then
 lineNum = math.huge
 -- If links is a number, process it. Negative values and expressions
 -- such as links=8/2 produced some interesting values with the old
 -- template, but we will ignore those for simplicity.
 elseif type(linksToNum) == 'number' and linksToNum >= 0 then
 -- The old template rounded down decimals to the nearest integer.
 lineNum = math.floor( linksToNum )
 if lineNum == 0 then
 -- In the old template, values of links between 0 and 0.999
 -- suppressed line breaks.
 lineNum = math.huge
 end
 else
 	if isLong==true then
 		lineNum = 3 -- Default to 3 links on long
 	else
 	lineNum = 10 -- Default to 10 on short
 end
 end
 return lineNum
end

-- Gets the prefix to put before the archive links.
local function getLinkPrefix
 -- Get the link prefix.
 local ret = ''
 if isLong==true then ---- Default of old template for long is 'Archive '
 	if type(prefix) == 'string' then
 		if prefix == 'none' then -- 'none' overrides to empty prefix
 			ret = ''
 		 else
 		 	ret = prefix
 		 	if space == 'yes' then
 		 		ret = ret .. ' '
 		 	end
		 	end
	 	else
	 		ret = 'Archive '
		end
	else --type is not long
		if type(prefix) == 'string' then
 	ret = prefix
 	if space == 'yes' then
 	 ret = ret .. ' '
 	end
 	end
 end
 return ret
end

-- Get the number to start listing archives from.
local function getStart( start )
 start = processNumArg( start )
 if start then
 return start
 else
 return 1
 end
end

-- Process the separator parameter.
local function getSeparator( sep )
 if sep and type(sep) == 'string' then
 if sep == 'dot' 
 or sep =='pipe'
 or sep == 'comma'
 or sep == 'tpt-languages' then
 return mw.message.new( sep .. '-separator' ):plain
 else
 return sep
 end
 else
 return nil
 end
end

-- Generates the list of archive links. glargs.max must be either zero (for
-- no archives) or a positive integer value.
local function generateLinks( glargs )
 if type( glargs ) ~= 'table' or not glargs.max or not glargs.prefix then
 error
 end
 -- If there are no archives yet, return a message and a
 -- link to create Archive one.
 if glargs.max == 0 then
 	if glargs.isLong == true then
 		glargs.max = 1 -- One archive redlink is displayed for Long format
 	else -- Short error and a creat link is displayed for short
 	return 'no archives yet (create)'
 end
 end
 -- Return an html error if the start number is greater than the 
 -- maximum number.
 local start = glargs.start or 1
 if start > glargs.max then
 return ''
 end
 local linkPrefix = glargs.linkPrefix or ''
 local lineNum = glargs.lineNum or 10
 local sep = '' -- Long default separator is cell elements, short is ', '
 local lineSep = '' -- Long default linebreak is row elements short is '\n'
 if glargs.isLong==true then 
 	sep = glargs.sep or ''
 	sep = sep .. ''
 else
 	sep = glargs.sep or mw.message.new( 'comma-separator' ):plain
 	lineSep = glargs.lineSep or ''
 end
 -- Generate the archive links.
 local lineCounter = 1 -- The counter to see whether we need a line break or not.
 local ret = {} -- A table containing the strings to be returned.
 if glargs.isLong == true then --Long version is a table
 	table.insert
 end
 for archiveNum = start, glargs.max do
 local link = mw.ustring.format
 table.insert
 -- If we don't need a new line, output a comma. We don't need
 -- a comma after the last link. 
 if lineCounter < lineNum and archiveNum < glargs.max then
 table.insert
 lineCounter = lineCounter + 1
 -- Output new lines if needed. We don't need a new line after
 -- the last link.
 elseif lineCounter >= lineNum and archiveNum < glargs.max then
 table.insert
 lineCounter = 1
 end
 end
 if glargs.isLong == true then --Long version is a table
 	table.insert
 end
 return table.concat( ret )
end

-- Determine if format should be long
local function findFormType( auto )
	if auto == nil or auto == '' then
		return false
	elseif auto == 'long' then
			return true
	else
		return false
	end
end

-- Get the archive data and pass it to generateLinks.
local function _main( args )
	local isLong = findFormType( args.auto )
 local prefix = getPrefix
 local lineNum = getLineNum
 local linkPrefix = getLinkPrefix
 local start = getStart( args.start )
 local max = getBiggestArchiveNum
 local sep = getSeparator( args.sep )
 local lineSep = getSeparator( args.linesep )
 local glargs = {
 start = start,
 max = max,
 prefix = prefix,
 linkPrefix = linkPrefix,
 isLong = isLong,
 sep = sep,
 lineNum = lineNum,
 lineSep = lineSep
 return generateLinks( glargs )
end

-- A wrapper function to make getBiggestArchiveNum available from
-- #invoke.
local function _count( args )
 local prefix = getPrefix
 local archiveMax = getBiggestArchiveNum( prefix )
 return archiveMax
end

function makeWrapper( func )
 return function( frame )
 -- If we are being called from #invoke, get the args from #invoke
 -- if they exist, or else get the arguments passed to the parent
 -- frame. Otherwise, assume the arguments are being passed directly
 -- in from another module or from the debug console.
 local origArgs
 if frame == mw.getCurrentFrame then
 origArgs = frame:getParent.args
 for k, v in pairs( frame.args ) do
 origArgs = frame.args
 break
 end
 else
 origArgs = frame
 end
 
 -- Ignore blank values for parameters other than "links",
 -- which functions differently depending on whether it is
 -- blank or absent.
 local args = {}
 for k, v in pairs( origArgs ) do
 if k == 'links' or v ~= '' then
 args[k] = v
 end
 end
 
 return func( args )
 end
end

return {
 main = makeWrapper( _main ),
 count = makeWrapper( _count )