local p = {}
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')

--  Returns all the dots (with absolute postions)
function p.data(frame)                                                          -- Returns the data of the graph
	local args = getArgs(frame)
	-- Dot related
	local yTable = {}
	local xTable = {}
	local xCount = 0
	local yCount = 0
	local isx;
	local dotTable = {}
	local x;
	-- Color related
	local colorTable = {}
	local num;
	local colorTime;
	-- X label related
	local xLabels = {}
	local xLCount = 0
	-- Y label related
	local yLabels = {}
	local yLCount = 0

	if yesno(args['yx']) == true then
		isx = false
	else
		isx = true
	end
	
	if args['x labels'] then                                                    -- Create xLabels
		for str in string.gmatch(args['x labels'], '([^, ]+)') do
	        table.insert(xLabels, str)
	        xLCount = xLCount + 1
	    end
	end
	
	if args['y labels'] then                                                    -- Create yLabels
		for str in string.gmatch(args['y labels'], '([^, ]+)') do
			table.insert(yLabels, str)
			yLCount = yLCount + 1
	    end
	end
	
	if args['dots'] then                                                        -- Creates xTable from dots
		local i = 0
		local j = 0
		
		for k, v in pairs(args) do
			if string.match(k, '%d+') 
			and not string.match(k, 'color%-') then
				table.insert(yTable, v)
				yCount = yCount + 1
			end
		end
		
		local cols = yCount / tonumber(args['dots'])
		
		if cols ~= math.floor(cols) then
			return '<span style="font-size:100%" class="error">The amount of y parameters (' .. yCount .. ') ÷ parameter dots (' .. args['dots'] .. ') is not a integer (' .. cols .. ')</span>'
		end
		
		while cols > i do
			local xValue = i / (cols - 1) * 100
			i = i + 1
			while tonumber(args['dots']) > j do
				j = j + 1
				table.insert(xTable, xValue)
				xCount = xCount + 1
			end
			j = 0
		end
	else                                                                        -- Divides args into the yTable and the xTable
		for k, v in pairs(args) do                                               
			if string.match(k, '%d+') 
			and not string.match(k, 'color%-') then
				if isx == false then
					table.insert(yTable, v)
					yCount = yCount + 1
					isx = true
				elseif not args['dots'] then
					table.insert(xTable, v)
					xCount = xCount + 1
					isx = false
				end
			end
		end
	end
	
	if xCount < yCount then                            
		return '<span style="font-size:100%"" class="error">The amount of x values (' .. xCount .. ') is less then the number y values (' .. yCount .. ')</span>'
	elseif xCount > yCount then
		return '<span style="font-size:100%" class="error">The amount of x values (' .. xCount .. ') is more then the number y values (' .. yCount .. ')</span>'
	end
	
	if args['color-even'] then                                                  -- Creates the colorTable if color-even is set
		colorTime = false
		for k, v in pairs(yTable) do
			if colorTime == true then
				colorTable[k] = args['color-even']
				colorTime = false
			else
				colorTime = true
			end
		end
	end
	
	if args['color-odd'] then                                                   -- Creates the colorTable if color-odd is set
		colorTime = true
		for k, v in pairs(yTable) do
			if colorTime == true then
				colorTable[k] = args['color-odd']
				colorTime = false
			else
				colorTime = true
			end
		end
	end
	
	for k, v in pairs(args) do                                                  -- Adds values to the colorTable if color-# is set
		if k == mw.ustring.match(k, 'color%-%d+') then
			num = mw.ustring.gsub(k, 'color%-', '')
			num = tonumber(num)
			colorTable[num] = v
		end
	end
	
	for k, y in pairs(yTable) do                                                -- Create the dotTable
		local innerDiv = mw.html.create('div')
		local div = mw.html.create('div')
		local size; 
		if args['size'] then
			size = tonumber(mw.ustring.match(args['size'], '(%d+)'))
		else
			size = 8
		end
		x = xTable[k]
		innerDiv
			:css('position', 'absolute')
			:css('top', '-' .. size / 2 .. 'px')
			:css('left', '-' .. size / 2 .. 'px')
			:css('line-height', '0')
			:wikitext('[[File:Location dot ', colorTable[k] or 'red', '.svg|', size, 'x', size, 'px]]')
		div
			:css('position', 'absolute')
			:css('bottom', y .. '%')
			:css('left', x .. '%')
			:wikitext(tostring(innerDiv))
		table.insert(dotTable, tostring(div))
	end
	
	for k, v in pairs(xLabels) do
		local innerDiv = mw.html.create('div')
		local div = mw.html.create('div')
		innerDiv
			:css('position', 'relative')
			:css('left', '-50%')
			:wikitext(v)
		div
			:css('position', 'absolute')
			:css('bottom', '0%')
			:css('left', (k - 1) / (xLCount - 1) * 100 .. '%')
			:wikitext(tostring(innerDiv))
		table.insert(dotTable, tostring(div))
	end
	
	for k, v in pairs(yLabels) do
		local div = mw.html.create('div')
		div
			:css('position', 'absolute')
			:css('bottom', (k - 1) / (yLCount - 1) * 100 .. '%')
			:css('left', '0%')
			:wikitext(v)
		table.insert(dotTable, tostring(div))
	end
	
	return table.concat(dotTable)
end

-- Create the legendTable
local function legend(args)
	local color;
	local aValue;
	local legendTable = {}
	for k, v in pairs(args) do                                                  -- Adds values to the table
		if k == mw.ustring.match(k, 'legend%-%a+') then
			color = mw.ustring.gsub(k, 'legend%-', '')
			v = '<div>[[File:Location dot ' .. (color or 'red') .. '.svg|8x8px]] (' .. color .. ') = ' .. v .. '</div>'
			table.insert(legendTable, v)
			aValue = true
		end
	end
	if aValue == true then
		return table.concat(legendTable)
	else
		return ''
	end
end

-- Get all the dots in a div tag
function p.graph(frame)         	                                        	-- Returns a graph with the dots on it
	if mw.ustring.match(p.data(frame), '<span') then                            -- Return error messages from p.data
		return p.data(frame) 
	end   
	local args = getArgs(frame)
	local picture = 'Blank.png'
	local div = mw.html.create('div')
	local center = mw.html.create('div')
	local container = mw.html.create('div')
	local top = mw.html.create('div')
	local size; 
	if args['size'] then
		size = tonumber(mw.ustring.match(args['size'], '(%d+)'))
	else
		size = 8
	end
	
	if args['width'] then
		if args['width'] == mw.ustring.match(args['width'], '(%d+)') then
			args['width'] = args['width'] .. 'px'
		end
	end

	if args['picture'] then                                                     -- Set local picture
		picture = args['picture']
	elseif yesno(args['square']) == true then
		picture = 'Transparent.png'
	end
	
	picture = mw.ustring.gsub(picture, '|.+', '')
	picture = mw.ustring.gsub(picture, '.-:', '')
	
	if p.data(frame) == '' then                                                 -- Don't make box if empty
		return ''
	end
	 
	if args['top'] then
		top                                                                     -- Create top text
			:css('font-weight', 'bold')
			:css('text-decoration', 'underline')
			:css('text-align', 'center')
			:wikitext(args['top'])
	end
	
	args['padding'] = args['padding'] or '10px'
	
	if not args['top'] and size/2 > 10 then
		args['padding'] = size/2
	end
	
	container                                                                   -- Creates container
		:css('width', args['width'] or '240px')
		:css('float', 'right')
		:css('position', 'relative')
		:wikitext('[[File:', picture, '|', args['width'] or '240px', ']]')
		:wikitext(p.data(frame))
	div                                                                         -- Creates box
		:css('width', args['width'] or '240px')
		:css('display', 'inline-block')
		:css('float', args['align'] or 'right')
		:css('margin', args['margin'] or '2px')
		:css('padding', args['padding'])
		:css('background', args['color'] or 'none')
		:wikitext(tostring(top))
		:wikitext(tostring(container))
		:wikitext(legend(args))
		:wikitext(args['bottom'])
		
	if yesno(args['border']) ~= false then                                      -- Creates box border
		div
			:css('border-style', 'solid')
			:css('border-color', 'black')
			:css('border-width', '3px')
	end
		
	if args['align'] == 'center' then                                           -- Centers output if needed
		center
			:addClass('center')
			:css('width', 'auto')
			:css('margin-left', 'auto')
			:css('margin-right', 'auto')
			:wikitext(tostring(div))
		return center                                                   
	else
		return div
	end
end

return p