-- ##### Localisation (L10n) settings #####
local L10n = {
	-- Template parameter names
	-- (replace values in quotes with local parameter names)
	para = {
		display = "display",
		from = "from",
		header = "header",
		title = "title",
		wikidata = "wikidata",
		demo = "demo",
	-- Other configuration settings
	config = {
		-- controls the format used for inline display, can be set to "box" (default) or "line"
		-- "box" example: https://en.wikipedia.org/wiki/Template:Attached_KML
		-- "line" example: https://sv.wikipedia.org/wiki/Mall:KML
		inline_format = "box",
	-- Other strings
	str = {
		inline = "inline", -- used with display parameter: (|display=inline) or (|display=title) or  or 
		title = "title", -- (as above)
		dsep = ",", -- separator between inline and title (comma in the example above)
		kml_prefix = "Template:Attached KML/", -- local KML files are stored as subpages of this location
		default_title = "Route map", -- default title for links at top of page, when title parameter not used in transclusion
		default_header = "", -- default header for links in inline box, when header parameter not used in transclusion
		kml_file = "KML 파일", -- text to display for link to raw KML file
		edit = "편집", -- text to display for link to edit KML file
		help = "도움말", -- text to display for help page link
		help_location	= ":en:Help:Attached KML", -- page to link to for help page link
		err_prepend	= "Attached KML", -- text to prepend to the error messages, when shown at top of page (display=title)
		cat	= { -- tracking categories: full wikimarkup required, or set to the empty string ("") to not to track the condition
			wikidata_kml = "분류:위키데이터의 KML을 사용하는 문서", -- tracks mainspace articles using KML from Wikidata
			local_kml = "분류:위키데이터에 없는 KML을 사용하는 문서", -- tracks mainspace articles not using KML from Wikidata
			error_mqid = "M", -- tracks malformed_qid error
			error_badqid = "W", -- tracks bad_qid error
			error_noitem = "N", -- tracks no_item error
			error_from = "F", -- tracks bad_from error
			error_nokml = "K", -- tracks no_kml error
		line = { -- these strings are only needed if using 'inline_format = "line"' configuration
			start = "", -- wikitext to display at start of line, may include image markup, should start with a space
			separator = "", -- text to display between links to external mapping providers, should include spaces

L10n.str.err = { -- error messages
	malformed_qid	= "Error: malformed item id in ",	-- item id doesn't match pattern (number with Q prefix)
	bad_qid		= "Error: item specified on Wikidata, or in ",	-- item doesn't have a P31→Q26267864 statement
	no_item		= "Error: item specified in  not found on Wikidata",	-- item not found on wikidata
	bad_from	= "Error: KML file not found, check ",	-- KML specified by from parameter doesn't exist
	no_kml		= "Error: KML file not found",	-- no KML file found

-- Masks for external mapping providers, in the form:
-- externalLinkMasks[index-number] = { short = "short-label", long = "long-label", link = "url" }'
-- The short label is used for the title links; the long label is used for the inline links
-- Links in the output will be ordered by index-number
-- Instead of kml file's raw url or encoded raw url, use __KML_URL__ or __KML_URL_E__
local externalLinks = {}
--externalLinks[1] = { 
--	short = "Bing",
--	long = "Display on Bing Maps",
--	link = "http://www.bing.com/maps/?mapurl=__KML_URL__"
--}

-- #### End of L10n settings ####

-- Table of available wikis, in the order that they are to be searched for kml files
-- 
local sites = {
		mw.ustring.match .. mw.ustring.gsub( mw.ustring.lower(mw.site.siteName), "[mp]edia", ""), 
		mw.ustring.sub,
		""

local p = {}

local function setCleanArgs(argsTable)
	local cleanArgs = {}
	for key, val in pairs(argsTable) do
		if type(val) == 'string' then
			val = val:match('^%s*(.-)%s*$')
			if val ~= '' then
				cleanArgs[key] = val
			end
		else
			cleanArgs[key] = val
		end
	end
	return cleanArgs
end

local function safeReplace
	-- avoids "Lua error: invalid capture index" that occurs with string.gsub when the replacement contains one or more literal % character
	local nonpattern_parts = mw.text.split
	return table.concat
end

local function makeTitleWikitext
	if err and L10n.str.err_prepend then
		err = mw.ustring.gsub
	end

	local titleLinks = {}
	for i, v in ipairs( externalLinks ) do
		titleLinks[i] = mw.ustring.format
	end
	return mw.ustring.format(
		"",
		titletext,
		err or table.concat
	) 
end

local function makeInlineWikitext
	local inlineLinks = {}
	for i, v in ipairs( externalLinks ) do
		inlineLinks[i] = mw.ustring.format
	end
	local editUrl = mw.ustring.gsub
	local wiki_link_class
	if mw.ustring.find then
		wiki_link_class = "plainlinks"
	else
		wiki_link_class = ""
	end

	if L10n.config.inline_format == "line" then
		return mw.ustring.format(
			"",
			headertext, L10n.str.line.start,
			err or table.concat,
			wiki_link_class, url, L10n.str.kml_file, editUrl, L10n.str.edit,
			L10n.str.help_location, L10n.str.help
		)
	end
	
	local text = mw.ustring.format
	
	if err or #inlineLinks > 0 then
		text = mw.ustring.format(
			"%s")
		)
	end
	
	return require('Module:Side box')._main({
		class = 'attached-kml',
		text = text
end

local function makeKmldataDiv
	return mw.ustring.format
end

local function makeError
	return mw.ustring.format(
		'%s',
		msg,
		mw.title.getCurrentTitle:inNamespaces and cat or ''
	)
end

local function getUrlFromQid( kml_qid )
	local pcall_result, kml_entity = pcall
	if not pcall_result then return nil, nil, nil, makeError end -- Error if entity doesn't exist

	local p31_claim = kml_entity:getBestStatements("P31") -- P31 is property "instance of"
	local has_good_p31
	for k, v in pairs( p31_claim ) do
		if (p31_claim[k] and p31_claim[k].mainsnak.snaktype == "value" and
			p31_claim[k].mainsnak.datavalue.type == "wikibase-entityid" and
			p31_claim[k].mainsnak.datavalue.value["numeric-id"] == 26267864) then
			has_good_p31 = true
		end
	end
	if not (has_good_p31) then -- Error if item isn't a kml file
		return nil, nil, nil, makeError
	end 

	local kml_sitelink
	local kml_siteindex
	local kml_url
	for i, v in ipairs( sites ) do
		kml_sitelink = kml_entity:getSitelink( v[1] )
		if kml_sitelink then
			kml_url = "https://" .. v[2] .. "/w/index.php?title=" .. mw.uri.encode .. "&action=raw"
			kml_siteindex = i
		end
		if kml_url then break end
	end
	return kml_url or nil, kml_sitelink or nil, kml_siteindex or nil, nil
end

-- Attempts to get url from linked wikidata items, will return nil if it can't
local function getUrlFromWikidata
	local entity = mw.wikibase.getEntityObject
	if not entity then return nil end			

	local kml_claim = entity:getBestStatements("P3096")	-- P3096 is property "KML file"
	
	if kml_claim then
		-- get the QID of the first value of the property
		if (kml_claim[1] and kml_claim[1].mainsnak.snaktype == "value" and kml_claim[1].mainsnak.datavalue.type == "wikibase-entityid") then
			local kml_qid = "Q" .. kml_claim[1].mainsnak.datavalue.value["numeric-id"]
			return getUrlFromQid( kml_qid )
		else
			return nil	-- TODO: error message
		end
	else
		return nil	-- TODO: error message
	end
end

function p.main(frame)
	local parent = frame.getParent(frame)
	local Args = setCleanArgs(parent.args)

	local qid = Args[L10n.para.wikidata] or nil

	-- get KML file url
	local wikiUrl, wikiTitle, wikiLink, trackingWikitext, kmlError
	if not (Args[L10n.para.from]) then
		if not qid then
			wikiUrl, wikiLink, siteindex, kmlError = getUrlFromWikidata
		elseif mw.ustring.find then
			wikiUrl, wikiLink, siteindex, kmlError = getUrlFromQid(qid)
		else
			kmlError = makeError
		end
	end
	
	if not (wikiUrl) then
		-- FIXME? this smells bad. shouldn't need to make a new title of a to_string
		-- from the current title and then turn it into text form
		wikiLink = Args[L10n.para.from] or mw.title.new(tostring(mw.title.getCurrentTitle)).text
		wikiLink = L10n.str.kml_prefix .. wikiLink
		wikiTitle = mw.title.new( wikiLink )
		if not (wikiTitle.exists) and not (kmlError) then
			if Args[L10n.para.from] then
				kmlError = makeError
			else
				kmlError = makeError
			end
		end
		wikiUrl = wikiTitle:fullUrl
		siteindex = 1
		trackingWikitext = mw.ustring.format(
			'%s',
			mw.title.getCurrentTitle:inNamespace(0) and L10n.str.cat.local_kml or ''
		)
	else
		trackingWikitext = mw.ustring.format(
			'%s',
			mw.title.getCurrentTitle:inNamespace(0) and L10n.str.cat.wikidata_kml or ''
		)
	end

	-- replace __KML_URL__ or __KML_URL_E__ with actual values
	local encodedWikiUrl = mw.uri.encode
	for i, v in ipairs( externalLinks ) do
		local el1 = safeReplace
		local el2 = safeReplace
		externalLinks[i]["link"] = el2
	end

	-- suppress errors and categories if demo parameter is set
	if Args[L10n.para.demo] then
		kmlError = nil
		trackingWikitext = ""
	end

	local wikitext = ""
	if Args[L10n.para.display] then
		local display = mw.text.split
		if display[1] == L10n.str.title or display[2] == L10n.str.title then
			wikitext = makeTitleWikitext
		end
		if display[1] == L10n.str.inline or display[2] == L10n.str.inline or (display[1] ~= L10n.str.title and display[2] ~= L10n.str.title) then
			local inlineWikitext = makeInlineWikitext
			wikitext = wikitext .. inlineWikitext
		end
	else
		wikitext = makeInlineWikitext
	end
	wikitext = wikitext .. makeKmldataDiv .. trackingWikitext

	return frame:extensionTag{
		name = 'templatestyles', args = { src = 'Module:Attached KML/styles.css' }

end