local concat = table.concat
local insert = table.insert
local sort = table.sort

local export = {}

function export.exists(frame)
	return require("Module:languages").getByCode(
		require("Module:parameters").process(frame.args, {
			[1] = {required = true}
		})[1]
	) and "1" or ""
end

do
	local function getByCode(frame, allow_etym)
		local plain = {}
		local args = require("Module:parameters").process(frame.args, {
			[1] = {required = true, type = "language", etym_lang = allow_etym},
			[2] = {required = true},
			[3] = plain,
			[4] = {type = "script"},
			[5] = plain,
		})
		return require("Module:language-like").templateGetByCode(args,
			function(itemname)
				local list
				if itemname == "getWikimediaLanguages" then
					list = args[1]:getWikimediaLanguages()
				elseif itemname == "getScripts" then
					list = args[1]:getScriptCodes()
				elseif itemname == "getAncestors" then
					list = args[1]:getAncestors()
				end
				if list then
					local retval = list[tonumber(args[3]) or error("Please specify the numeric index of the desired item.")]
					if retval then
						if type(retval) == "string" then
							return retval
						else
							return retval:getCode()
						end
					else
						return ""
					end
				end
				if itemname == "transliterate" then
					return (args[1]:transliterate(args[3], args[4], args[5])) or ""
				elseif itemname == "makeDisplayText" then
					return (args[1]:makeDisplayText(args[3], args[4])) or ""
				elseif itemname == "makeEntryName" then
					return (args[1]:makeEntryName(args[3], args[4])) or ""
				elseif itemname == "makeSortKey" then
					return (args[1]:makeSortKey(args[3], args[4])) or ""
				elseif itemname == "countCharacters" then
					return args[4]:countCharacters(args[3] or "")
				elseif itemname == "findBestScript" then
					return args[1]:findBestScript(args[3] or ""):getCode()
				end
			end
		)
	end
	
	-- Used by the following JS:
	-- * [[WT:ACCEL]]
	-- * [[WT:EDIT]]
	-- * [[WT:NEC]]
	function export.getByCode(frame)
		return getByCode(frame, false)
	end
	
	function export.getByCodeAllowEtym(frame)
		return getByCode(frame, true)
	end
end

function export.getByCanonicalName(frame)
	local lang = require("Module:languages").getByCanonicalName(
		require("Module:parameters").process(frame.args, {
			[1] = {required = true}
		})[1],
		nil,
		true
	)
	return lang and lang:getCode() or ""
end

function export.getCanonicalName(frame)
	local args = require("Module:parameters").process(
		require("Module:yesno")(frame.args.parent) and frame:getParent().args or frame.args,
		{
			[1] = {required = true},
			["return_if_invalid"] = {type = "boolean"},
		}
	)
	local lang = require("Module:languages").getByCode(args[1], nil, true)
	return lang and lang:getCanonicalName() or not args.return_if_invalid and "" or args[1]
end

function export.getFull(frame)
	local args = require("Module:parameters").process(
		require("Module:yesno")(frame.args.parent) and frame:getParent().args or frame.args,
		{
			[1] = {required = true, type = "language", etym_lang = true},
		}
	)
	return args[1]:getFullCode()
end

function export.getChildren(frame)
	local args = require("Module:parameters").process(
		require("Module:yesno")(frame.args.parent) and frame:getParent().args or frame.args,
		{
			[1] = {required = true, type = "language", etym_lang = true},
		}
	)
	local children = args[1]:getChildren()
	
	sort(children, function(a, b)
		return a:getCanonicalName() < b:getCanonicalName()
	end)
	
	local list = {}
	for _, child in ipairs(children) do
		insert(list, "* " .. child:makeWikipediaLink() .. ": " .. "<code>" .. child:getCode() .. "</code>")
	end
	
	return concat(list, "\n")
end

return export