Belgekirina modulê[biafirîne]
-- Creates a timeline for an item based on various properties

local p = {}
local wikidata = require('Module:Wîkîdane2')
local linguistic = require('Module:Zimanzanî')
local fb = require('Module:Fallback')

local function formatpage(page, lang)
-- same text for singular and plural, most of the time, they can be distinguished by the presence of a "-" but that does not always work, see Q11927173
	if not page then 
		return nil
	end
	return fb._langSwitch({ -- singular
		de = 'S. ' .. page,
		en = 'p. ' .. page,
		fr = 'p. ' .. page,
		nb = 's. ' .. page,
		nn = 's. ' .. page,
		}, lang)
end

local function getauthor(item, lang)
	return wikidata.formatStatements{entity=item, property = 'P50', lang=lang}
end

local function getISBN(item, lang)
	local ISBN = wikidata.formatStatements{entity = item, property = 'P212', lang=lang, numval = 1}
	if ISBN then 
		return 'ISBN ' ..ISBN
	end
end

local function getLink(item, lang)
	local links = wikidata.formatStatements{entity = item, property = 'P854', numval = 1, lang=lang}
	if links then
		return fb._langSwitch({
			de = '[' .. links .. ' online]',
			en = '[' .. links .. ' read online]',
			fr = '[' .. links .. ' lire en ligne]',
			nb = '[' .. links .. ' les online]',
			nn = '[' .. links .. ' les online]',
			}, lang)
	end
end

local function getVolume(item, lang)
	local volume = wikidata.formatStatements{entity = item, property = 'P478', numval = 1, lang=lang}
	if volume then
		return fb._langSwitch({
			de = 'Band ' .. volume,
			en = 'vol. ' .. volume,
			}, lang)
	end
end

local function getDoi(item, lang)
	local doi = wikidata.formatStatements({entity=item, property = 'P356', numval = 1, lang=lang}) -- what to do if several value
	if not doi then
		return nil
	end
	return '<small>' .. 'doi: [//dx.doi.org/' .. doi .. ' ' .. doi .. ']' .. '</small>' -- needs i18n ?
end

local function getPmid(item, lang)
	local pmid = wikidata.formatStatements({entity=item, property = 'P698', numval = 1, lang=lang}) -- what to do if several value
	if not pmid then
		return nil
	end
	return '<small> Pub Med ID: [//www.ncbi.nlm.nih.gov/pubmed/?term=' .. pmid .. ' ' .. pmid .. '] </small>' -- needs i18n ?
end

local function getEditor(item, lang)
	local editortable = wikidata.getClaims({entity=item, property='P98'})
	if not editortable then 
		return nil
	end
	local editor = wikidata.formatStatements({entity=item, property='P98', lang=lang}) -- should have a "formatClaims" function to avoid double work
	if #editortable > 1 then return
		fb._langSwitch({ --plural
			de = editor .. ' (Hrsg.)',
			en = editor .. ' (eds.)',
			nb = editor .. ' (red.)',
			nn = editor .. ' (red.)',
			}, lang)
	else
		return fb._langSwitch({ -- singular
			de = editor .. ' (Hrsg.)',
			en = editor .. ' (ed.)',
			nb = editor .. ' (red.)',
			nn = editor .. ' (red.)',
			}, lang)
	end
		
end

local function getedition(item, lang)
	local ednumber = wikidata.formatStatements({entity=item, property = 'P393', lang=lang, numval = 1}) 
	if not ednumber then 
		return nil
	end
	local ord = require('Module:Ordinal')._ordinal
	return fb._langSwitch({ 
		de = ednumber .. '. Auflage', 
		en = ord{ednumber, lang = 'en'} .. ' edition',
		fr = ord{ednumber, lang = 'fr'} .. ' édition',
		nb = ord{ednumber, lang = 'nb'} .. ' utgave',
		nn = ord{ednumber, lang = 'nn'} .. ' utgave',
		}, lang)
end

local function getarticletitle(item, lang)
	local title = wikidata.formatStatements({entity=item, property = 'P1476', lang=lang}) or wikidata.formatStatements({entity=item, property = 'P357', lang=lang})
	if not title then
		return '[[' .. item.id .. ']] (ti senavek malê pêşkêşkirin!)'
	end
	return fb._langSwitch({
		de = '„' .. '[[' .. item.id .. '|' .. title .. ']]' .. '“',
		en = '"' .. '[[' .. item.id .. '|' .. title .. ']]' .. '"',
		fr = '«' ..'[[' .. item.id .. '|' ..  title .. ']]' .. '»',
		nb = '«' ..'[[' .. item.id .. '|' ..  title .. ']]' .. '»',
		nn = '«' ..'[[' .. item.id .. '|' ..  title .. ']]' .. '»',
		} , lang)
end

local function getbooktitle(item, lang)-- needs i18n some languages do not use this format
	local title = wikidata.formatStatements({entity=item, property = 'P1476', lang=lang}) or wikidata.formatStatements({entity=item, property = 'P357', lang=lang})
	if not title then
		return '[[' .. item.id .. ']] (ti senavek malê pêşkêşkirin!)'
	end
	return '<i>' .. '[[' .. item.id .. '|' .. title .. ']]' .. '</i>'
end

local function getissue(item, lang)
	return  wikidata.formatStatements({entity=item, property = 'P433', lang=lang})
end

local function getpublisher(item, lang)
	return wikidata.formatStatements({entity=item, property = 'P123', lang=lang})
end

local function getpublishdate(item, lang)
	return  wikidata.formatStatements({entity=item, property = 'P577', lang=lang})
end

local function geturl(item, lang)
	return wikidata.formatStatements({entity=item, property = 'P854', lang=lang})
end

local function getlicense(item, lang)
	return wikidata.formatStatements{entity=item, property = 'P275', lang=lang}
end

local function getjournal(item, lang) -- get the title property rather than the label
	local journal = wikidata.getClaims({entity = item, property = 'P1433', exlcudespecial = true})
	if not journal then
		return nil
	end
	if #journal > 1 then 
		return "error, source has too much publishing info"
	end
	local journalid = 'Q' .. journal[1].mainsnak.datavalue.value["numeric-id"]
	local journaltitle = wikidata.formatStatements({item = journalid , property = 'P1433', lang=lang})
	if not journaltitle then
		journaltitle = wikidata._getLabel(journalid)
	end
	return '<i>[[' .. journalid .. '|' .. journaltitle .. ']]</i>'
end

local function citebook(item, lang, page)
	local publishdate = getpublishdate(item, lang)
	local author = getauthor(item, lang)
	local editor = getEditor(item, lang)
	local title = getbooktitle(item, lang)
	local publisher = getpublisher(item, lang)
	local edition = getedition(item, lang)
	local isbn = getISBN(item, lang)
	local doi = getDoi(item, lang)
	local pmid = getPmid(item, lang)
	local link = getLink(item, lang)
	local volume = getVolume(item, lang)
	local pagenumber = formatpage(page, lang)
	local license = getlicense(item, lang)

	local fields = {}
	table.insert(fields, author)
	table.insert(fields, editor)
	table.insert(fields, title)
	table.insert(fields, edition)
	table.insert(fields, volume)
	table.insert(fields, publisher)
	table.insert(fields, publishdate)
	table.insert(fields, pagenumber)
	table.insert(fields, isbn)
	table.insert(fields, doi)
	table.insert(fields, pmid)
	table.insert(fields, link)
	table.insert(fields, license)
	return linguistic.conj(fields, lang, "comma")
end

local function citearticle(item, lang, page)
	local author = getauthor(item, lang)
	local title = getarticletitle(item, lang)
	local publisher = getpublisher(item, lang)
	local publishdate = getpublishdate(item, lang)
	local pagenumber = formatpage(page, lang)
	local journal = getjournal(item, lang)
	local issue = getissue(item, lang)
	local publishdate = getpublishdate(item, lang)
	local doi = getDoi(item, lang)
	local pmid = getPmid(item, lang)
	local link = getLink(item, lang)
	local volume = getVolume(item, lang)
	local pagenumber = formatpage(page, lang)
	local license = getlicense(item, lang)
	
	local fields = {}
	table.insert(fields, author)
	table.insert(fields, title)
	table.insert(fields, publisher)
	table.insert(fields, journal)
	table.insert(fields, volume)
	table.insert(fields, issue)
	table.insert(fields, publishdate)
	table.insert(fields, pagenumber)
	table.insert(fields, doi)
	table.insert(fields, pmid)
	table.insert(fields, link)
	table.insert(fields, license)
	return linguistic.conj(fields, lang, "comma")
end

function p.citeitem(item, lang, page)
	if not item then return nil end
	if type(item) == 'string' then
		item = mw.wikibase.getEntityObject(item)
	end
	if not item then
		return "invalid item id"
	end
	if wikidata.getClaims({entity = item, property = 'P1433'}) then -- if item has "edition of" is a book, else an article, needs a better solution
		return citearticle(item, lang, page)
	else
		mw.log('Citing as book')
		return citebook(item, lang, page)
	end
end

function p.cite(frame)
	local lang = frame.args.lang
	if not lang or lang == '' then
		lang = frame:preprocess('{{int:lang}}')
	end
	local page = frame.args.page
	if page == '' then
		page = nil
	end
	return p.citeitem(frame.args.item, lang, page)
end

function p.reflist(frame)
	local list = mw.text.split( frame.args[1], ' ')
	local lang = frame.args.lang
	if not lang or lang == '' then
		lang = frame:preprocess('{{int:lang}}')
	end
	local str = ''
	for i, j in pairs(list) do
		str = str ..  '<li> ' .. p.citeitem(mw.text.trim(j),lang) .. '</li>'
	end
	return str
end

return p