-- This template implements 
--
local p = {}
local lang = mw.getContentLanguage
local Date -- lazy initialization

local function ifexist(page)
 if not page then return false end
 if mw.title.new(page).exists then return true end
 return false
end

local function isempty( s )
	return not s or s:match( '^%s*(.-)%s*$' ) == ''
end

local function splitnumandref( s )
	s = s:match( '^%s*(.-)%s*$' )
	local t1 = mw.text.unstrip(s)
 local t2 = s:match( '^' )
	if( t1 == t2 ) then
		local t3 = s:match( '^[%d][%d,]*(.-)$' )
		return t1, t3
	else
		return s, ''
	end
end

local function formatnumR(num)
	return tonumber(lang:parseFormattedNumber(num))
end

local function formatnum(num)
	return lang:parseFormattedNumber(num) and lang:formatNum(lang:parseFormattedNumber(num)) or num
end

-- this function creates an array with the {year, population, percent change}
local function getpoprow
	local pop, popref = splitnumandref( popstr or '')
	local ppop, ppopref = splitnumandref( ppopstr or '')
	local percent = ''
	local yearnum = formatnumR(mw.ustring.gsub(year or '', '^%s*([%d][%d][%.%d]+).*$', '%1') or '')
	local pyearnum = formatnumR(mw.ustring.gsub(pyear or '', '^%s*([%d][%d][%.%d]+).*$', '%1') or '')
	local popnum = formatnumR(pop)
	local ppopnum = formatnumR(ppop)
	if( linktype == 'US' or linktype == 'USA' ) then
		if( (yearnum or 0) >= 1790 and yearnum <= current_year and math.fmod(math.floor(yearnum), 10) == 0) then
			if( yearnum < current_year ) then
				year = '' .. year .. ''
 			elseif( ifexist(tostring(yearnum) .. '년 미국 인구 조사') ) then
				year = '' .. year .. ''
			end
		end
	end
	if(percentages ~= 'off') then
		local pstr = '—&nbsp;&nbsp;&nbsp;&nbsp;'
		if(popnum ~= nil and ppopnum ~= nil and (ppopnum > 0)) then
			if(percentages == 'pagr') then
				pstr = mw.ustring.format('%.2f', 100*math.abs(math.pow(popnum/ppopnum,1/(yearnum-pyearnum)) - 1))
			elseif(percentages == 'monthly') then
				if Date == nil then Date = require('Module:Date')._Date end
				local date1 = Date(year)
				local date2 = Date(pyear)
				local diff = date1 - date2
				local months = (diff.age_days/(365.25/12))
				pstr = mw.ustring.format('%.2f', 100*math.abs(math.pow - 1))
			else
				pstr = mw.ustring.format('%.1f', 100*math.abs(popnum/ppopnum - 1))
			end
			if( popnum < ppopnum ) then
				pstr = '−' .. pstr .. '%'
			else
				pstr = '+' .. pstr .. '%'
			end
		elseif(popnum ~= nil and ppopnum ~= nil and (ppopnum == popnum)) then
			pstr = mw.ustring.format .. '%'
		end
		percent = pstr
	end
	-- strip the fractional part of the year, if there is one
	year = mw.ustring.gsub(year or '', '^%s*([%d][%d][%d]+)%.[%d]*', '%1')
	
	return {year, formatnum(pop) .. popref, percent }
end

-- this function creates an array with table header labels
local function getheadrow
	-- year cell	
	if(yearname == '') then
		yearname = '연도'
	end
	-- population cell
	if(popname == '') then
		popname = '인구'
	end

	-- percentages cell
	if( percentages ~= 'off' and percentname == '') then
		if( percentages == 'pagr' ) then
			percentname = ''
		elseif( percentages == 'monthly' ) then
			percentname = ''
		else
			percentname = ''
		end
	end
	return {yearname, popname, percentname}
end

-- this function builds the json for the population graph
local function graphjson
	local yearcount = #data
	local graphargs = {
		['width'] = gwidth,
		['height'] = gheight,
		['type'] = 'line',
		['yAxisTitle'] = 'Population',
		['yAxisMin'] = 0,
		['xAxisTitle'] = 'Year',
		['xAxisAngle'] = '-45',
		['yGrid'] = 'y',
		['yAxisFormat'] = ',d',
		['x'] = '',
		['y'] = ''
	local firstpoint = true
	for offset = 1,yearcount do
		local x,y = data[offset][1], data[offset][2]
		-- delink if necessary
		if x:match('^%s*%[%^%[%*%|([^%[%]]*)%]%]') then
			x = x:match('^%s*%[%^%[%*%|([^%[%]]*)%]%]')
		end
		y = formatnumR(y)
		if x and y then
			graphargs['x'] = graphargs['x'] ..  .. x
			graphargs['y'] = graphargs['y'] ..  .. y
			firstpoint = false
		end
	end
	local Graph = require('Module:Graph')
	
	return Graph.chart({args = graphargs})
end

local function rendergraph
	local graph = frame:extensionTag{
			name = 'templatestyles', 
			args = { src = 'Graph:Chart/styles.css'} 

	if(gthumb ~= '') then
		local graphdiv = mw.html.create('div')
		graphdiv
		return tostring(graphdiv)
	end
	
	return ''
end

-- this function renders the population table in a vertical format
local function rendervertical
	-- define a couple helper functions
	local function addrowcell
		cell = trow:tag(tag)
		cell
	end
	local function addheadcell
		cell = trow:tag('th')
		cell
	end

	local colspan = 3
	local yearcount = #data
	local argcount = 2*yearcount
	
	if( isempty(width) ) then
		width = '15em'
	end
	
	-- override the value of cols if percol has been specified
	if( percol > 0 ) then
		cols = math.floor( (yearcount - 1) / percol ) + 1
	end
	
	-- compute the number of rows per col
	local rowspercol = math.floor( (yearcount - 1) / cols ) + 1

	-- specify the colspan for the title and footer lines
	if( cols > 1 ) then
		colspan = cols
	else
		if (head[3] == '') then 
			colspan = 2
		else
			colspan = 3
		end
	end

	-- compute outer table width
	local twidth = width
	if( (cols > 1) and width:match('^%s*[%d]+[%w]+%s*$') ) then
		local widthnum = mw.ustring.gsub( width, '^%s*([%d]+)([%w]+)%s*$', '%1' )
		local widthunit = mw.ustring.gsub( width, '^%s*([%d]+)([%w]+)%s*$', '%2' )
		twidth = tostring(widthnum*cols) .. widthunit
	end
	
	-- create the outer table
	local root = mw.html.create('table')
	root
	-- add title
	local caption = root:tag('caption')
	caption
		
	-- add the graph line (if top graph)
	if((graphpos == 'top' or graphpos == 't') and graph ~= '') then
		row = root:tag('tr')
		cell = row:tag('td')
		cell
		graph = ''
	end
	
	-- loop over columns and rows within columns
	local offset = 1
	local t = root
	for c = 1,cols do
		-- add inner tables if we are rendering more than one column
		if( cols > 1) then
			if (c == 1) then
				row = root:tag('tr')
				row:attr
				cell = row:tag('td')
				cell:css
			else
				cell = row:tag('td')
				cell
			end
			t = cell:tag('table')
			t
		end
		-- start column headers
		local hrow = t:tag('tr')
		hrow:css
		-- year header
		addheadcell
		-- population header
		addheadcell
		-- percentages header
		if( head[3] ~= '' ) then
			addheadcell
		end
		-- end column headers
		-- start population rows
		for r = 1,rowspercol do
			-- generate the row if we have not exceeded the rowcount
			-- shade every fifth row, unless shading = off
			local s = 'off'
			if( math.fmod((c - 1)*rowspercol + r, 5) == 0 and r ~= rowspercol) then
				s = shading
			end
			if(offset <= yearcount) then
				-- start population row
				local prow = t:tag('tr')
				-- year cell
				addrowcell
				-- population cell
				addrowcell
				-- percentage cell
				if( not isempty(head[3]) ) then
					addrowcell
				end
				-- end population row
				offset = offset + 1
			end
		end
	end

	-- add the graph line (if bottom graph)
	if((graphpos == 'bottom' or graphpos == 'b') and graph ~= '') then
		row = root:tag('tr')
		cell = row:tag('td')
		cell
		graph = ''
	end
	-- add the footnote line 	
	if( footnote ~= '') then
		row = root:tag('tr')
		cell = row:tag('td')
		cell
	end
	
	return graph .. tostring(root)
end

-- this function renders the population table in a horizontal format
local function renderhorizontal
	local row
	local cell
	local yearcount = #data
	local argcount = 2*yearcount
	
	-- override the value of rows if perrow has been specified
	if( perrow > 0 ) then
		rows = math.floor( (yearcount - 1) / perrow ) + 1
	end
	
	-- compute the number of cols per row
	local colsperrow = math.floor( (yearcount - 1) / rows ) + 1

	-- create the outer table
	local root = mw.html.create('table')
	root
	-- create title row
	row = root:tag('tr')
	cell = row:tag('th')
	cell

	-- add the graph line (if top graph)
	if((graphpos == 'top' or graphpos == 't') and graph ~= '') then
		row = root:tag('tr')
		cell = row:tag('td')
		cell
		graph = ''
	end

	-- loop over rows and columns within rows
	local offset = 1
	for r = 1,rows do
		local rowoffset = offset
		-- render the years
		row = root:tag('tr')
		cell = row:tag('th')
		cell:wikitext(head[1])
		for c = 1,colsperrow do
			cell = row:tag('td')
			if(offset <= yearcount) then
				cell:wikitext(data[offset][1])
			else
				cell:css
			end
			offset = offset + 1
		end
		-- render the pop
		offset = rowoffset
		row = root:tag('tr')
		cell = row:tag('th')
		cell:wikitext(head[2])
		for c = 1,colsperrow do
			cell = row:tag('td')
			if(offset <= yearcount) then
				cell:wikitext(data[offset][2])
			else
				cell:css
			end
			offset = offset + 1
		end
		-- render the percentages
		if(head[3] ~= '') then
			offset = rowoffset
			row = root:tag('tr')
			cell = row:tag('th')
			cell:wikitext(head[3])
			for c = 1,colsperrow do
				cell = row:tag('td')
				if(offset <= yearcount) then
					cell:wikitext(data[offset][3])
				else
					cell:css
				end
				offset = offset + 1
			end
		end
	end
	
	-- add the graph line (if bottom graph)
	if((graphpos == 'bottom' or graphpos == 'b') and graph ~= '') then
		row = root:tag('tr')
		cell = row:tag('td')
		cell
		graph = ''
	end
	
	-- add the footnote line 	
	if( footnote ~= '') then
		row = root:tag('tr')
		cell = row:tag('td')
		cell
	end
	
	return graph .. tostring(root)
end

-- this is the main function
function p.poptable(frame)
	local data = {}
	local style = {}
	local args = frame.args[1] and frame.args or frame:getParent.args

	local title			= args['title']			or ''
	local align			= args['align']			or ''
	local clear			= args['clear']			or ''
	local direction		= args['direction']		or ''
	local percentages	= args['percentages']	or ''
	local state			= args['state']			or ''
	local linktype		= args['type']			or ''
	local shading		= args['shading']		or 'on'
	local width			= args['width']			or ''
	local subbox		= args['subbox']		or ''
	local popname		= args['pop_name']		or ''
	local yearname		= args['year_name']		or ''
	local percentname = args['percent_name'] or ''
	local footnote		= args['footnote']		or ''
	local alignfn		= args['align-fn']		or ''
	local source		= args['source']		or ''
	local graphpos = args['graph-pos'] or ''
	local graphwidth = args['graph-width'] or ''
	local graphheight = args['graph-height'] or ''
	local percol = tonumber(args['percol'])	or 0
	local cols	 = tonumber(args['cols'])	or 1
	local perrow = tonumber(args['perrow'])	or 0
	local rows	 = tonumber(args['rows'])	or 1
	style['year'] = args['year_style']
	style['pop'] = args['pop_style']
	style['pct'] = args['pct_style']

	-- setup classes and styling for outer table
	local class = direction == 'horizontal' and 'wikitable' or 'toccolours'
	if( state == 'collapsed' ) then
		class = class .. ' collapsible collapsed'
	end

	if( isempty(title) ) then
		title = '연도별 인구'
	end

	if( isempty(align) ) then
		align = direction ~= 'horizontal' and 'right' or 'center'
	end
	
	if( isempty(alignfn) ) then
		alignfn = 'left'
	end
	
	if( isempty(clear) ) then
		clear = align == 'center' and '' or align
	end
	
	local margin = '0.5em 0 1em 0.5em'
	if( align == 'left' ) then
		margin = '0.5em 1em 0.5em 0'
	elseif( align == 'none' ) then
		margin = '0.5em 1em 0.5em 0'
	elseif( align == 'center' ) then
		margin = '0.5em auto'
		align = ''
	end

	if( isempty(subbox) ) then
		style['table'] =
			'border-spacing: 0;' ..
			(align ~= '' and 'float:' .. align .. ';' or '') ..
			(clear ~= '' and 'clear:' .. clear .. ';' or '') ..
			'margin:' .. margin .. ';'
	else
		style['table'] =
			'margin:0;' ..
			'border-collapse:collapse;' ..
			'border:none;'
	end	
		
	-- setup the footer text
	if( source ~= '' ) then
		source = '출처: ' .. source
		if( footnote ~= '' ) then
			footnote = footnote .. ''
		end
	end
	footnote = footnote .. source
	
	-- setup the data header cols/rows
	local head = getheadrow
	
	-- count the total number of population rows
	local argcount = 0
	local rowcount = 0
	for k, v in pairs( args ) do
		if ( (type( k ) == 'number') and (not isempty(args[k])) ) then
			if( k >= 1 and math.floor(k) == k and k > argcount) then
				argcount = k
			end
			if( math.fmod == 0 ) then
				rowcount = rowcount + 1
			end
		end
	end

	-- here is where we build all the data for the table
	-- loop over columns and rows within columns
	local pyear = ''
	local ppop = ''
	local offset = 1
	local current_year = tonumber(os.date)
	for r = 1,rowcount do
		-- skip blank rows
		while(isempty(args[offset]) and offset <= argcount) do
			offset = offset + 2
		end
		-- generate the row if we have not exceeded the rowcount
		if(offset <= argcount) then
			table.insert(data, getpoprow )
			pyear = args[offset]
			ppop = args[offset+1] or ''
			offset = offset + 2
		end
	end

	local graph = ''
	graphpos = graphpos:lower
	-- now that we have the data for the table, render it in the requested format

	if (direction == 'horizontal') then
		if graphpos ~= '' then
			local gwidth = tonumber(graphwidth) or 200
			local gheight= tonumber(graphheight) or 170
			local gthumb = 
				(graphpos == 'r' or graphpos == 'right' and 'right') or
				(graphpos == 'l' or graphpos == 'left' and 'left') or ''
			graph = rendergraph
		end
		return renderhorizontal
	else
		if graphpos ~= '' then
			local gwidth = tonumber(graphwidth) or (170 * cols)
			local gheight= tonumber(graphheight) or 170
			local gthumb = 
				(graphpos == 'r' or graphpos == 'right' and 'right') or
				(graphpos == 'l' or graphpos == 'left' and 'left') or ''
			graph = rendergraph
		end
		return rendervertical
	end

end