require('strict')

local p = {}

local score_version = '"2.22.0"'
local page_namespace = 104
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local error_module = require('Module:Error')

local function error_message(txt)
	return error_module['error']({message = 'Error: incorrect use of Tscore template: ' .. txt})
end

local function getnextpage(start, name)
	local stdargs = {['start'] = '', ['next'] = false, ['score'] = '', ['cont'] = '', ['width'] = '180', ['layout'] = '' }
	
	if string.match(name, '^Page:') == 'Page:' then
		name = string.sub(name, 8)
	end
	local strona = mw.title.makeTitle('Page', name)
	local kod = strona:getContent()
	if kod == nil then
		return nil
	end
	kod = string.match(kod, '{{[SsTt]score%s*|.*cont *= *' .. start .. '.*}}')
	if kod == nil then
		return nil
	end
	kod = string.sub(kod, 1, string.find(kod, '[^!]}}'))
	
	local wynik = {}
	for kod2 in string.gmatch(kod, '|[^|]*') do
		local kod3 = mw.text.trim(string.sub(kod2, 2 ))
		local n = string.find(kod3, '=')
		local kod4 = mw.text.trim( string.sub(kod3, 1, n - 1))
		if stdargs[kod4] ~= nil then
			stdargs[kod4] = mw.text.trim(string.sub(kod3, n + 1))
		else
			wynik[kod4] = mw.text.trim(string.sub(kod3, n + 1))
		end
	end
	
	local wynik2 = {}
	if stdargs['next'] then
		wynik2 = getnextpage(start, stdargs['next'])
		if type(wynik2) ~= 'table' then
			return wynik2
		end
	end
	
	for k, v in pairs(wynik) do
		if wynik2[k] ~= nil then
			wynik[k] = wynik[k] .. ' ' .. wynik2[k]
		end
		wynik[k] = string.gsub( wynik[k], '{{!}}', '|')
	end
	return wynik
end

local function scal(args)
	-- initial setup
	local stdargs = {['start'] = '', ['next'] = false, ['score'] = '', ['cont'] = '', ['width'] = '', ['layout'] = '', ['debug'] = false}
	local kod_score = ''
	local warning = ''
	local argn = {}
	local title = mw.title.getCurrentTitle()
	local paper_size = 'a2'
	
	-- process arguments
	for k, v in pairs(args) do
		if type(k) == 'number' then
			return error_message('unnamed template parameter encountered; maybe | was used instead of {{!}}')
		elseif type(k) == 'string' and stdargs[k] ~= nil then
			stdargs[k] = v
		end
	end
	
	stdargs['next'] = yesno(stdargs['next'])
	stdargs['debug'] = yesno(stdargs['debug'])
	
	-- limit width
	stdargs['width'] = tonumber(stdargs['width']) or 180
	local max_width = 400
	if title:inNamespace(page_namespace) then
		max_width = 140
	end
	stdargs['width'] = math.min(stdargs['width'], max_width)
	
	-- optimize paper size: a2 / a3 / a4 ; width in milimeters
	if stdargs['width'] < 190 then
		paper_size = 'a4'
	elseif stdargs['width'] < 280 then
		paper_size = 'a3'
	end
	
	stdargs['width'] = tostring(stdargs['width'])
	
	-- error checks
	if stdargs['score'] == '' then
		return error_message('no score code')
	end
	
	if stdargs['start'] ~= '' then
		if not stdargs['next'] then
			warning = warning .. error_message('no next page defined') .. '<br>'
		end
		if stdargs['cont'] ~= '' then
			warning = warning .. error_message('the first page cannot be a sunbsequent page') .. '<br>'
		end
	end
	
	if not title:inNamespace(page_namespace) then
		if stdargs['cont'] ~= '' then
			return warning
		elseif stdargs['start'] ~= '' and stdargs['next'] then
			argn = getnextpage(stdargs['start'], stdargs['next'])
			if argn == nil then
				return error_message('next page not found')
			elseif type(argn) == 'string' and argn == '' then
				return error_message('no continueing Tscore template found on the next page')
			elseif type(argn) ~= 'table' then
				return error_message('unidentified error')
			end
		end
	end
	
	-- do … something?
	for k, v in pairs(args) do
		if type(k) == 'string' and stdargs[k] == nil then
			kod_score = kod_score .. '\n' .. k .. ' = '
			if string.sub(k, 1, 1) == 'l' then
				kod_score = kod_score .. '\\lyricmode '
			end
			kod_score = kod_score .. '{ ' .. v;
			if argn[k] ~= nil then
				kod_score = kod_score .. ' ' .. argn[k]
			end
			kod_score = kod_score .. ' }\n'
		end
	end
	
	-- do … something?
	kod_score = kod_score .. "\n\\paper { #(set-paper-size \"" .. paper_size .. "\") }\n\\header { tagline = ##f }\n\\version " .. score_version
	kod_score = kod_score .. "\n\\score {\n\\midi { }\n\\layout { line-width = #" .. stdargs['width'] .. '\n' .. stdargs['layout'] .. "}\n" .. stdargs['score'] .. " }"
	
	-- add debugging info
	local current_frame = mw.getCurrentFrame()
	if stdargs['debug'] then
		warning = warning .. '\n' .. tostring(mw.html.create('code'):wikitext(current_frame:extensionTag('nowiki', kod_score))) .. '\n'
	end
	
	-- return score
	return warning .. current_frame:extensionTag('score', kod_score, {raw = '1', midi = '1', vorbis = '1' })
end

function p.genscore(frame)
	return scal(getArgs(frame))
end

return p