require('strict');

local p = {}
--[[--------------------------< M A K E _ C I T E R E F _ I D >------------------------------------------------

Generates a CITEREF anchor ID if we have at least one name or a date.  Otherwise returns nil.

namelist_t is one of the authorlast{} (|last1= ... |lastn=) or editorlast{} (|editorlast1= ... |editorlastn=) sequence
tables chosen in that order.  year is the value from |year=

]]

local function make_citeref_id (namelist_t, year)
	local names_t={};															-- a sequence table for the one to four names and year
	for i,v in ipairs (namelist_t) do											-- loop through the list and take up to the first four last names
		names_t[i] = v;
		if i == 4 then break end												-- if four then done
	end
	table.insert (names_t, year);												-- add the year at the end; may be the only entry
	local id = table.concat(names_t);											-- concatenate names_t and year for CITEREF id
	if '' ~= id then															-- if concatenation is not an empty string
		return "CITEREF" .. id;													-- add the CITEREF prefix
	else
		return;																	-- return nil; no reason to include CITEREF id in this citation
	end
end

--[[--------------------------< P . C I T E >------------------------------------------------------------------

implements Template:Cite LSA

]]

function p.cite(frame)
	local args = frame:getParent().args
	local authorfirst = {}
	local authorlast = {}
	local editorfirst = {}
	local editorlast = {}

	for k,v in pairs(args) do
		local num, i, j;

		if string.find(k, "first") ~= nil then
			if string.find(k, "%d") ~= nil then
				i,j = string.find(k, "%d")
				num = string.sub(k,i,j)
				num = tonumber(num)
			else
				num = 1
			end
			if string.find(k, "editor") ~= nil then
				editorfirst[num] = v
			else
				authorfirst[num] = v
			end
		elseif string.find(k, "last") ~= nil then
			if string.find(k, "%d") ~= nil then
				i,j = string.find(k, "%d")
				num = string.sub(k,i,j)
				num = tonumber(num)
			else
				num = 1
			end
			if string.find(k, "editor") ~= nil then
				editorlast[num] = v
			else
				authorlast[num] = v
			end
		end
	end
	
	local publisher = args.publisher
	local author = args.last													-- required
	local authorlist;
	
	if table.getn(authorlast) < 1 and publisher ~= nil then
		authorlist=publisher .. ". "
		author=""
	elseif table.getn(authorlast) > 0 then
		local alimit = table.getn(authorlast)
		for i,v in ipairs(authorlast) do
			if i == 1 then
				authorlist = authorlast[1] .. ", " .. authorfirst[1];
			elseif i > 1 and i <= alimit then
				authorlist = authorlist .. authorfirst[i] .. " " .. authorlast[i];
			end
			if i+1 == alimit then
				authorlist = authorlist .. ", and "
			elseif alimit == 1 then
				authorlist = authorlist .. ". "
			elseif alimit > 2 and i ~= alimit then
				authorlist = authorlist .. "; "
			elseif i == alimit then
				authorlist = authorlist .. ". "
			end
		end
	end
	
	local editorlist = nil
	if editorlast ~= {} then
		editorlist = ""
		local elimit = table.getn(editorlast)
		for i,v in ipairs(editorlast) do
			editorlist = editorlist .. editorfirst[i] .. " " .. editorlast[i]
			if i+1 == elimit and editorlist ~= " " then
				editorlist = editorlist .. ", and "
			elseif elimit > i and editorlist ~= " " then
				editorlist = editorlist .. ", "
			end
		end
		if editorlist == "" or editorlist == " " then
			editorlist = ""
		end
	end
	
	local year = args.year														-- required
	if author and year then
		authorlist = authorlist .. year .. ". "
	elseif author then
		authorlist = authorlist .. " <span class=\"cslsa-error\">Missing year</span>" .. ". "
	elseif year then
		authorlist = "<span class=\"cslsa-error\">Missing author name</span>" .. year .. ". "
	else
		authorlist = "<span class=\"cslsa-error\">Missing author name; missing year</span>" .. ". "
	end
	
	local title = (args.title and args.title) or "<span class=\"cslsa-error\">Missing title</span>"
	local journal = args.journal
	local chapter = args.chapter
	local series = args.seriestitle or args.series
	local volume = args.volume
	local issue = (args.issue and '(' .. args.issue .. ')') or '';				-- journal cites only
	local edition = args.edition
	local pages = (args.pages and args.pages .. ".") or '';
	local url = args.url
	local doi = args.doi
	if doi ~= nil then
		url='https://doi.org/'..doi
	end
	local accessdate = (args.accessdate and " Accessed " .. args.accessdate .. ".") or '';
	local place = args.place
	local citation = nil
	if journal ~= nil then
		journal = "\'\'" .. journal .. "\'\'";									-- italicize journal
		volume = (volume and volume or '') .. issue;							-- composit volume and issue
		if '' ~= volume then
			journal = journal .. " " .. volume;
		end
		if url then
			title = "[" .. url .. " " .. title .. "]. ";							-- link title with url
		end

		citation = authorlist .. title .. journal .. ". " .. pages .. accessdate;

	elseif journal == nil then
		if chapter ~= nil then
			if url ~= nil then
				citation = authorlist .. "[" .. url .. " " .. chapter .. "]."
			else
				citation = authorlist .. chapter .. ". "
			end
			if title ~= nil then
				citation = citation .. "\'\'" .. title .. "\'\'"
				if editorlist ~= nil and editorlist ~= "" then
					citation = citation .. " ed. by " .. editorlist
				end
				if '' ~= pages then
					citation = citation .. ", " .. pages;
				else
					citation = citation .. ". "
				end
				if edition ~= nil and volume ~= nil then
					citation = citation .. edition .. ", " .. volume .. "; " 
				elseif edition ~= nil and volume == nil then
					citation = citation .. edition .. "; "
				elseif edition == nil and volume ~= nil then
					citation = citation .. volume .. "; "
				end
				if series ~= nil then
					citation = citation .. "(" .. series .. "). "
				end
				if place ~= nil and publisher ~= nil then
					citation = citation .. place .. ": " .. publisher .. "."
				elseif place ~= nil and publisher == nil then
					citation = citation .. place .. "."
				elseif place == nil and publisher ~= nil then
					citation = citation .. publisher .. "."
				end
				if url ~= nil then
					citation = citation .. accessdate .. ". "
				end
			end
		else
			if title ~= nil then
				if url ~= nil then
					citation = authorlist .. "\'\'[" .. url .. " " .. title .. "]\'\'"
				else
					citation = authorlist .. "\'\'" .. title .. "\'\'"
				end
				if editorlist ~= nil and editorlist ~= "" then
					citation = citation .. ", ed. by " .. editorlist
				end
				if '' ~= pages then
					citation = citation .. ", " .. pages;
				else
					citation = citation .. ". "
				end
				if edition ~= nil and volume ~= nil then
					citation = citation .. edition .. ", " .. volume .. "; " 
				elseif edition ~= nil and volume == nil then
					citation = citation .. edition .. "; "
				elseif edition == nil and volume ~= nil then
					citation = citation .. volume .. "; "
				end
				if series ~= nil then
					citation = citation .. "(" .. series .. "). "
				end
				if place ~= nil and publisher ~= nil then
					citation = citation .. place .. ": " .. publisher .. "."
				elseif place ~= nil and publisher == nil then
					citation = citation .. place .. "."
				elseif place == nil and publisher ~= nil then
					citation = citation .. publisher .. "."
				end
				if url ~= nil then
					citation = citation .. accessdate .. "."
				end
			end
		end
	end

	local namelist_t = {};														-- holds selected authorlast or editorlast name list	
	if #authorlast > 0 then														-- is there an author list?
		namelist_t = authorlast;												-- use the author list
	elseif #editorlast > 0 then													-- if not, is there an editor list?
		namelist_t = editorlast;												-- use the editor list
	end

	local citeref_id;
	if #namelist_t > 0 then														-- if there are names in namelist_t
		citeref_id = make_citeref_id (namelist_t, year);						-- go make the CITEREF anchor
		citeref_id = mw.uri.anchorEncode (citeref_id);							-- and anchor encode it
	end

	return table.concat ({
		frame:extensionTag ({name='templatestyles', args={src='Module:Cite LSA/styles.css'}}),	-- add templates styles
		'<cite class="citation cslsa"',											-- open the cite tag with class attribute
		citeref_id and ('id="' .. citeref_id .. '">') or '">';					-- add id attribute and close the tag; or simply close when no id
		citation,																-- add the citation
		'</cite>'																-- add the terminal cite tag
		});
end

return p