Implements {{frp-IPA}}. Locality data in Module:frp-IPA/data.


local m_link = require("Module:links")
local frp = require("Module:languages").getByCode("frp")
local m_IPA = require("Module:IPA")
local format_accent = require("Module:accent qualifier").format_qualifiers
local locs = mw.loadData("Module:frp-IPA/data")
local get_section = require("Module:utilities").get_section
local m_temp = require("Module:template parser")
local m_form_of = require("Module:form of")

local export = {}

local accents = mw.loadData("Module:labels/data/lang/frp")

local codes = {"orbl", "orbs", "mcn", "cmt", "nch", "onch", "frb", "ofrb", "vds", "ovds", "vls", "ovls",
	"vld", "pms", "svy", "osvy", "gnv", "ognv",	"bgs", "brs", "obrs", "dmb", "odmb", 
	"bjl", "objl", "lyn", "olyn", "frz",  "ofrz", "dph", "odph", "apl"}
local allowed_codes = require("Module:table/listToSet")(codes)
export.codes = codes

local references = {"ALF", "AIS", "ALLy", "GPSR", "DFP", "LTA", "PVA", "FEW"}
export.references = references

-- |ALF=maps 31, 472; cf. also 1211
-- |AIS=map 71
local function make_ref(args)
	local no_ref_given = true
	local output_text = "\n[[WT:AFRP#Sources|Sources]]:"
	for _,ref in ipairs(references) do
		if args[ref] then
			no_ref_given = false
			output_text = output_text .. "\n* [" .. locs[ref] .. " " .. ref .. "] " .. args[ref]
		end
	end
	return no_ref_given and "" or output_text
end

local function record(data,field)
	return function(value)
		if value ~= "" then
			data[field] = value
		end
		return ""
	end
end

-- format: "[pron]<ortho>(loc1,loc2,...)ref"
local function parse(text,loc,require_pron)
	local data = {}
	text = text:gsub("[/%[][^/%[%]]+[/%]]",record(data,"pron"))
	if require_pron and not data.pron then error("Missing pronunciation in "..loc) end
	text = text:gsub("^<([^<>]+)>",record(data,"ortho"))
	text = text:gsub("^%(([^%(%)]+)%)",record(data,"locs"))
	if text:match("^[A-Z]") then -- reference must start with capital letter
		if not locs[text] then
			error("Invalid reference: " .. text)
		end
		data.ref = text
	elseif text ~= "" then error("Invalid input ("..loc.."): "..text) end
	return data
end

local function link(text)
	return m_link.full_link({lang = frp, term = text})
end

local function format_ortho(text)
	if text then
		return " ⟨" .. m_link.full_link({lang = frp, term = text}) .. "⟩"
	end
	return ""
end

local function parse_loc(group,code)
	local data = locs[group][code]
	if not data then
		error("Invalid code " .. code .. " for " .. accents[group])
	end
	if type(data) == "string" then -- allow redirect once
		code,data = data,locs[group][data]
	end
	local wiki = (type(data) == "table") and data.wiki or code
	return {wiki, code, frp:makeSortKey(code)}
end

local function format_locs(group,text,no_paren)
	if not text then
		return ""
	end
	local locs = mw.text.split(text,",",true)
	for i,loc in ipairs(locs) do
		locs[i] = parse_loc(group,loc)
	end
	table.sort(locs,function(a,b) return a[3]<b[3] end)
	for i,loc in ipairs(locs) do
		locs[i] = "[[w:"..loc[1].."|"..loc[2].."]]"
	end
	return (no_paren and "%s" or " (%s)"):format(table.concat(locs,", "))
end

-- check if each parameter name is valid
local function check_groups(args)
	for a,_ in pairs(args) do
		if type(a) == "number" then
			error("This template does not accept numbered arguments.")
		end
		if not allowed_codes[a] and not locs[a] then
			error("Invalid accent code: "..a)
		end
	end
end

local function gather_data(data,args,require_pron)
	-- reference
	data.ref = make_ref(args)
	for _,a in ipairs(codes) do
		if args[a] and args[a] ~= "" then
			data[a] = {}
			for term in mw.text.gsplit(args[a],";",true) do
				local loc_data = parse(term, a, require_pron)
				if loc_data.ref and not args[loc_data.ref] then
					error("Reference used but not specified: " .. loc_data.ref)
				end
				table.insert(data[a], loc_data)
				if loc_data.pron then
					data[a].has_pron = true
				end
				if loc_data.ortho then
					data[a].has_ortho = true
				end
			end
		end
	end
end

-- `next` doesn't seem to work
local function is_empty(args)
	for _, _ in pairs(args) do
		return false
	end
	return true
end

local function scrape(pagename)
	local content = mw.title.new(pagename):getContent()
	content = get_section(content,{"Franco-Provençal","Alternative forms"},3)
	for t_name,t_args,t_src,t_dx in m_temp.findTemplates(content) do
		if t_name == "frp-alt" then
			return t_args
		end
	end
	error("Scraping failed.")
end

function export.show(frame)
	local args = frame:getParent().args
	local require_pron = true
	if is_empty(args) then
		args = scrape(mw.loadData("Module:headword/data").page.full_raw_pagename)
		require_pron = false
	end
	check_groups(args)
	local data = {}
	gather_data(data,args,require_pron)
	-- go through each lect in order
	local show = {}
	local hide = {}
	for _,a in ipairs(codes) do
		if data[a] and data[a].has_pron then
			local accent = format_accent(frp,{a})
			table.insert(hide,'* '..accent)
			local prons = {}
			for _,term in ipairs(data[a]) do
				if term.pron then
					table.insert(prons,{pron = term.pron})
					local hide_text = m_IPA.format_IPA(frp, term.pron)
						.. format_ortho(term.ortho)
						.. (term.ref and "<sup>"..term.ref.."</sup>" or "")
						.. format_locs(a, term.locs)
					table.insert(hide,'** '..hide_text)
				end
			end
			table.insert(show,'* '..accent..': '..m_IPA.format_IPA_multiple(frp, prons, nil, 1))
		end
	end
	return '<div class="vsSwitcher" data-toggle-category="pronunciations">'
		.. '<span class="vsToggleElement"></span>'
		.. '<div class="vsShow">\n'
		.. table.concat(show,'\n')
		.. '\n</div><div class="vsHide">\n'
		.. table.concat(hide,'\n')
		.. data.ref
		.. '</div></div>[[Category:Franco-Provençal terms with IPA pronunciation]]'
end

function export.show_alt(frame)
	local args = frame:getParent().args
	check_groups(args)
	local data = {}
	gather_data(data,args)
	-- go through each lect in order
	local show = {}
	local hide = {}
	for _,a in ipairs(codes) do
		if data[a] and data[a].has_ortho then
			local accent = format_accent(frp,{a})
			table.insert(hide,'* '..accent)
			local orthos = {}
			for _,term in ipairs(data[a]) do
				if term.ortho then
					local term_link = link(term.ortho)
					table.insert(orthos, term_link)
					table.insert(hide,'** ' .. term_link
						.. (term.ref and "<sup>"..term.ref.."</sup>" or "")
						 .. format_locs(a, term.locs))
				end
			end
			table.insert(show,accent..' '..table.concat(orthos,", "))
		end
	end
	return '<div class="vsSwitcher" data-toggle-category="alternative forms">'
		.. '<span class="vsToggleElement"></span>'
		.. '<div class="vsShow">\n'
		.. '* ' .. table.concat(show,'; ')
		.. '\n</div><div class="vsHide">\n'
		.. table.concat(hide,'\n')
		.. '</div></div>'
end

function export.show_altform(frame)
	local args = frame:getParent().args
	local allowed_para = { [1] = true, [2] = true }
	local ns = mw.loadData("Module:headword/data").page.namespace
	if ns == "Template" then
		allowed_para.pagename = true
	end
	for key,_ in pairs(args) do
		if not allowed_para[key] then
			error("Parameter "..key.." not used by this template.")
		end
	end
	local pagename = args.pagename or mw.loadData("Module:headword/data").pagename
	local lemma_args = scrape(args[1])
	local data = {}
	gather_data(data, lemma_args)
	local locs = {}
	local loc_text
	local seen
	for _,a in ipairs(codes) do
		if data[a] then
			for _,term in ipairs(data[a]) do
				if term.ortho == pagename then
					seen = true
					loc_text = format_locs(a, term.locs, true)
					if loc_text and loc_text ~= "" then
						table.insert(locs, loc_text)
					end
				end
			end
		end
	end
	if not seen then
		error("Gathering localities failed. Please specify manually.")
	end
	if #locs > 0 then
		loc_text = " documented in the following location(s): " .. table.concat(locs, "; ")
	end
	return m_form_of.format_form_of{
		lemma_face = "term",
		lemmas = { { lang = frp, term = args[1], gloss = args[2] } },
		text = "Alternative form of",
		posttext = loc_text
	}
end


return export