-- --


--[=[ 2015-06-28
Unterstützung für {{Cite book}}
]=]


-- Global
local Zitation
local Selbst = "Vorlage:Cite book"
local KategorieBeginn  =  "Wikipedia:Vorlagenfehler"
local Kategorien       =
     { Intern              = { s = "/Interner Fehler" },
       Parameter           = { s = "/Parameterfehler" },
       ISBNistFormalFalsch = { s = "/Parameter ISBNistFormalFalsch" }
     }
     
local ParValid = {
    author              = { author1 = true, authors=true }, 
    first               = { first1 = true},
    last                = { last1 = true},
    authorlink          = { authorlink1 = true},
    editor              = { editor1 = true, editors=true },
    title               = true,
--    TitelErg            = true,
--    Sammelwerk          = true,
    series              = true,
--    BandReihe           = true,
--    HrsgReihe           = true,
--    NummerReihe         = true,
    volume              = true,
    issue               = true,
    edition             = true,
    publisher           = true,
    location            = true,
    date                = true,
    year                = { date=true },
    month               = { date=true,
                            week=true },
    week                = { date=true },
    day                 = { date=true,
                            week=true },
    chapter             = true,
    pages               = { page=true },
--    Spalten             = true,
--    ArtikelNr           = true,
    isbn                = true,
--    issn                = true,
--    Umfang              = true,
    language            = true,
    comment             = true,
--    Originaltitel       = true,
--    Originalsprache     = true,
    origpublisher       = true,
    origlocation        = true,
    origyear            = true,
--    ["Übersetzer"]      = { ["Übersetzerin"]=true },
--    VerlagEA            = true,
---    OrtEA               = true,
--    JahrEA              = true,
--    arxiv               = true,
--    bibcode             = true,
    doi                 = true,
--    jstor               = true,
    lccn                = true,
    oclc                = true,
--    pmc                 = true,
--    pmid                = true,
    urn                 = true,
--    ZDB                 = true,
    id                  = true,
    url                 = true,
    accessdate          = true,
    format              = true,
    kbyte               = true,
    quote               = true,
--    Typ                 = true,
    ["display-authors"] = true,
    Vorlage             = true }
    
local ParMap = {
    author           = { "bas",      "Autor" },
    editor           = { "bas",      "Hrsg" },
    ["new.title"]        = { "bas",      "Titel" },
--    TitelErg         = { "bas",      "TitelErg" },
    ["new.work"]         = { "bas",      "Werk" },
--    WerkErg          = { "bas",      "WerkErg" },
    series           = { "serie",    "Reihe" },
--    _seriesvolume     = { "serie",    "Band" },
    _serieseditor     = { "serie",    "Hrsg" },
--    _seriesissue      = { "serie",    "Nummer" },
    volume           = { "print",    "Band" },
    issue            = { "print",    "Nummer" },
    edition          = { "print",    "Auflage" },
    publisher        = { "bas",      "Verlag" },
    location         = { "print",    "Ort" },
    date             = { "bas",      "Datum" },
    ["new.chapter"]  = { "fragment", "Kapitel" },
    pages            = { "fragment", "Seiten" },
--    Spalten          = { "fragment", "Spalten" },
--    ArtikelNr        = { "fragment", "ArtikelNr" },
    isbn             = { "id",       "ISBN" },
--    ISBNformalFalsch = { "id",       "ISBNfalsch" },
    issn             = { "id",       "ISSN" },
--    Umfang           = { "print",    "Umfang" },
    language         = { "bas",      "Sprache" },
    comment          = { "bas",      "Kommentar" },
    quote            = { "bas",      "Zitat" },
--    Originaltitel    = { "orig",     "Titel" },
--    Originalsprache  = { "orig",     "Sprache" },
--    ["Übersetzer"]   = { "orig",     "Translator" },
    origlocation     = { "ed1",      "Ort" },
    origyear         = { "ed1",      "Jahr" },
    origpublisher    = { "ed1",      "Verlag" },
--    Online           = { "www",      "Weblink" },
    url              = { "www",      "URL" },
    accessdate       = { "www",      "Abruf" },
    format           = { "www",      "Format" },
    kbyte            = { "www",      "KBytes" },
    arxiv            = { "id",       "arXiv" },
    bibcode          = { "id",       "Bibcode" },
    doi              = { "id",       "DOI" },
--    DNB              = { "id",       "DNB" },
    jstor            = { "id",       "JSTOR" },
    lccn             = { "id",       "LCCN" },
    oclc             = { "id",       "OCLC" },
    pmc              = { "id",       "PMC" },
    pmid             = { "id",       "PMID" },
    urn              = { "id",       "URN" },
--    ZDB              = { "id",       "ZDB" },
    id               = { "id",       "ID" },
--    Typ              = { "leise",    "Typ" },
    Vorlage          = { "leise",    "Vorlage" } }

-- Noch nicht im neuen Format umgesetzt
--|last
--|first
--|authorlink

--|last1
--|first1
--|authorlink1

--|last999
--|first99
--|authorlink99

--|display-authors

--|trans_chapter

--|chapterurl

--|editor-first
--|editor-last
--|editor-link

--|editor1-last
--|editor1-first
--|editor1-link

--|editor5-last
--|editor5-first
--|editor5-link

--|display-editors

--|type

local Fehler = false

-- Nicht unterstützt
--|others
--|doi_brokendate
--|asin
--|publication-date

-- Nicht unterstützt da durch Wikipedia:Zitierregeln festgelegt
--|author-name-separator
--|author-separator
--|separator
--|postscript
--|lastauthoramp

-- Nicht unterstützt, da das eigentliche Buch keine Online-Ressource ist, auf die Bezug genommen wird
--|archiveurl
--|archivedate
--|deadurl

-- Nicht unterstützt, da sie bei Büchern keine Verwendung finden
--|arxiv
--|bibcode
--|issn
--|jfm
--|jstor
--|pmc
--|pmid
--|rfc

--|ol
--|osti
--|ssrn
--|zbl
--|id
--|mr

-- Derzeit allgemein nicht unterstützt
--|laysummary
--|laysource
--|laydate
--|ref
--|via
--|registration
--|subscription
--|author-mask
--|at
--|nopp

-- Nutzung in en-Wiki nicht mehr erwünscht
--| coauthors --> Include coauthors in authors or use separate authorn or lastn/firstn to list coauthors
--| month --> Use date instead.
--| day --> Use date instead.

-- Nicht unterstützte Alias der englischen Vorlage
-- author1, author2 .. --> bitte last1, last2 .. nutzen (Parameter ist nur für den Nachnamen gedacht, wird aber ab und an mit dem vollen Namen verwechselt)


local function fault( a )
    -- Formatiere Fehler mit class=error
    -- Parameter:
    --     a  -- string mit Text
    local r
    if type( Zitation ) == "table" then
        r = Zitation.fault( a )
    else
        r = string.format( "<span class=\"error\">%s</span>", a )
    end
    return r
end -- fault()



local function fehler( art, anzeige )
    -- Ein Fehler ist aufgetreten
    -- Parameter:
    --     art      -- string mit Schlüsselwort zum Typ
    --     anzeige  -- string mit Einzelheiten, oder nil
    local t
    if not Fehler then
        Fehler = { Intern    = { s = "Interner Fehler",
                                 k = "Intern" },
                   Modul     = { s = "Modul-Seite fehlt",
                                 k = "Intern" },
                   Vorlage   = { s = "Vorlagen-Seite fehlt",
                                 k = "Intern" },
                   Format    = { s = "Parameterformat" },
                   Konflikt  = { s = "Parameterkonflikt",
                                 k = "Parameter" },
                   Parameter = { s = "Parameterfehler",
                                 k = "Parameter" },
                   Pflicht   = { s = "Pflichtparameter fehlt",
                                 k = "Parameter" },
                   Wert      = { s = "Werte ungültig",
                                 k = "Parameter" },
                   Doppelt   = { s = "Mehrfache Angabe von Parametern",
                                 k = "Parameter" },
                   ISBNistFormalFalsch = { k = "ISBNistFormalFalsch" },
                   TitelP              = { k = "TitelP" }
                 }
    end
    t = Fehler[ art ]
    if t then
        if anzeige then
            local s = mw.text.nowiki( anzeige )
            if t.e then
                t.e = string.format( "%s; %s", t.e, s )
            else
                t.e = s
            end
        end
        if t.k then
            local wk = Kategorien[ t.k ]
            if wk then
                wk.e = true
            else
                Fehler.Intern.e     = "Wartungskat " .. wk
                Kategorien.Intern.e = true
            end
        end
    else
        Fehler.Intern.e     = string.format( "fehler(%s) %s",
                                             art, anzeige or "???" )
        Kategorien.Intern.e = true
    end
end -- fehler()



local function fehlerliste()
    -- Auflistung aller Fehlermeldungen und Kategorien
    -- Rückgabewert: string mit formatiertem Ergebnis
    local r = ""
    local s
    if Fehler then
        local sep = ""
        for k, v in pairs( Fehler ) do
             if v.e then
                r = string.format( "%s%s*** %s: %s",
                                   r,  sep,  v.s or "",  v.e )
                sep = " "
            end
        end -- for k, v
        r = "<br />" .. fault( r )
    end
    for k, v in pairs( Kategorien ) do
        if v.e then
            if v.s:sub( 1, 1 ) == "/" then
                s = Selbst
            else
                s = ""
            end
            r = string.format( "%s[[Kategorie:%s/%s%s]]",
                               r, KategorieBeginn, s, v.s )
        end
    end -- for k, v
    return r
end -- fehlerliste()



-------------------------------------------------------------------------



function autorenListe(args, max)
    local names = {}
    local r = ""
    local first = ""
    local sep = ""
    local AddEtAl = false

    -- Prüfung ob mehr als die maximal erwünschte Anzahl von Autoren vorhanden sind
 	for i = max+1, 99, 1 do
 		if args["last" .. i] then
 			max = tonumber(args["display-authors"]) or 1
 			AddEtAl = true
 		end
 	end	
 	
    for i = 1, max, 1 do
        if (i == 1) then
        	if args["last"] or args["last" .. i] then
        		if args["last"] and  args["last" .. i] then
        			fehler( "Doppelt", "'last' und 'last1'" )
    			end
        		if args["first"] and args["first" .. i] then
        			fehler( "Doppelt", "'first' und 'first1'" )
        		end
 
				local linkcount = 0
				local linkparams =  ""
				if args["author-link"] then
					linkcount = linkcount +1 
					linkparams = linkparams .. ", 'author-link'"
				end
				if args["author-link1"] then
					linkcount = linkcount +1 
					linkparams = linkparams .. ", 'author-link1'"
				end
				if args["authorlink"] then
					linkcount = linkcount +1 
					linkparams = linkparams .. ", 'authorlink'"
				end
				if args["authorlink1"] then
					linkcount = linkcount +1 
					linkparams = linkparams .. ", 'authorlink1'"
				end
 
				if linkcount > 1 then
					linkparams = string.gsub(linkparams, ", (['%w%d%-]+)", "%1",1)
					linkparams = string.gsub(linkparams, ", (['%w%d%-]+)$", " und %1")
					fehler( "Doppelt", linkparams )
				end
 
        		if args["last"] or args["last1"] then
            		first = ""
            		if args["first"] or args["first" .. i] then
            			first = (args["first"] or args["first" .. i]) .. " "
            		end
            		if args["authorlink"] or args["author-link"] or args["authorlink1"] or args["author-link1"] then
            			r = string.format("%s%s[[%s|%s%s]]", r, sep, args["authorlink"] or args["author-link"] or args["authorlink1"] or args["author-link1"], first, args["last"] or args["last1"])
        			else
            			r = string.format("%s%s%s%s", r, sep, first, args["last"] or args["last1"])
    				end
        			sep = ", "
        		end
			elseif args["first" .. i] then
    			fehler( "Parameter", "'first" .. i.."' ohne 'last" .. i.."'" )
			elseif args["first"] then
    			fehler( "Parameter", "'first' ohne 'last'" )
    		end		
    	else
            if args["last" .. i] then
            	first = ""
            	if args["first" .. i] then
            		first = args["first" .. i] .. " "
            	end
            	if args["authorlink"..i] then
            		r = string.format("%s%s[[%s|%s%s]]", r, sep, args["authorlink"..i], first, args["last"..i])
        		else
            		r = string.format("%s%s%s%s", r, sep, first, args["last"..i])
    			end
        		sep = ", "
        	elseif args["first" .. i] then
        		fehler( "Parameter", "'first" .. i.."' ohne 'last"..i"'" )
        	end
        	-- TODO Fehlermeldung, wenn ein Autor fehlt --> z.B. last1 und last3 aber nicht last2
    	end
	end
    if AddEtAl then
		r = string.format("%s %s", r, 'et al.')	
	end
 
    if r == "" then
    	r = nil
	end
    return r, AddEtAl;
end --autoren_liste

function hrsgListe(args, max)
    local names = {}
    local r = ""
    local first = ""
    local sep = ""
    --local max = tonumber(args["display-editors"]) or 5
    
    for i = 1, max, 1 do
        if (i == 1) then
        	if args["editor-last"] or args["editor" .. i .. "-last"] then
	        	--Doppelte udn uneinheitlich genutzte Parameter
	    		if args["editor-last"] and  args["editor" .. i .. "-last"] then
	    			fehler( "Doppelt", "'editor-last' und 'editor" .. i .. "-last'" )
		    		if args["editor-last"] then
			    		if args["editor" .. i .. "-first"] then
			    			fehler( "Doppelt", "'editor-last' verlangt 'editor-first' nicht 'editor" .. i .. "-first'" )
			    		end
			    		if args["editor" .. i .. "-link"] then
			    			fehler( "Doppelt", "'editor-last' verlangt 'editor-link' nicht 'editor" .. i .. "-link'" )
			    		end
		    		else
			    		if args["editor-first"] then
			    			fehler( "Doppelt", "'editor" .. i .. "-last' verlangt 'editor" .. i .. "-first' nicht 'editor-first'" )
			    		end
			    		if args["editor-link"] then
			    			fehler( "Doppelt", "'editor" .. i .. "-last' verlangt 'editor" .. i .. "-link' nicht 'editor-link'" )
			    		end
	    			end
	    		end
	    		
	    		if args["editor-first"] and  args["editor" .. i .. "-first"] then
	    			fehler( "Doppelt", "'editor-first' und 'editor" .. i .. "-first'" )
	    		end
	    		if args["editor-link"] and  args["editor" .. i .. "-link"] then
	    			fehler( "Doppelt", "'editor-link' und 'editor" .. i .. "-link'" )
	    		end
				-- Formatierung
				if args["editor-first"] or args["editor" .. i .. "-first"] then
					first = (args["editor-first"] or args["editor" .. i .. "-first"]) .. " "
				else
					first = ""
				end
				
        		if args["editor-link"] or args["editor" .. i .. "-link"] then
        			r = string.format("%s%s[[%s|%s%s]]", r, sep, args["editor-link"] or args["editor" .. i .. "-link"], first, args["editor-last"] or args["editor" .. i .. "-last"])
    			else
        			r = string.format("%s%s%s%s", r, sep, first, args["editor-last"] or args["editor" .. i .. "-last"])
				end
    			sep = ", "
		    elseif args["editor" .. i .. "-first"] then
    			fehler( "Parameter", "'editor" .. i .. "-first' ohne 'editor" .. i .. "-last'" )
			elseif args["editor-first"] then
    			fehler( "Parameter", "'editor-first' ohne 'editor" .. i .. "-last'" )  
        	end	
        			
    	else
            if args["editor" .. i .. "-last"] then
            	if args["editor" .. i .. "-first"] then
            		first = args["editor" .. i .. "-first"] .. " "
            	else
            		first = ""
            	end
        		if args["editor" .. i .. "-link"] then
        			r = string.format("%s%s[[%s|%s%s]]", r, sep, args["editor" .. i .. "-link"], first, args["editor" .. i .. "-last"])
    			else
        			r = string.format("%s%s%s%s", r, sep, first, args["editor" .. i .. "-last"])
				end
        		sep = ", "
        	elseif args["editor" .. i .. "-first"] then
        		fehler( "Parameter", "'editor" .. i .. "-first' ohne 'editor" .. i .. "-last'" )
        	end
    	end
	end

    if args["editor" .. max+1 .. "-last"] then
		r = string.format("%s %s", r, 'et al.')	
	end
	
    if r == "" then
    	r = nil
	end
    return r;
end -- hrsgListe

local Autor = function ( args, max )
--|author
--|authors
--|last1 |first1 |author-link1
-- ..
--|last9 |first9 |author-link9
--|display-authors

--Nicht unterstützt
--|authorn --> nutze lastn
--|author1 --> nutze author
--|coauthors --> nutze authors
    local r = args.author or args.authors
    local a , etal = autorenListe( args, max or 9);
    if r and a then
    	fehler( "Doppelt", "'author(s)' und 'last*'" )
    elseif r then
        if args.author and args.authors then
            fehler( "Doppelt", "'author' und 'authors'" )
        end
		if (args["authorlink"] or args["author-link"] or args["authorlink1"] or args["author-link1"]) then
			if args.author then
				r = string.format("[[%s|%s]]", args["authorlink"] or args["author-link"] or args["authorlink1"] or args["author-link1"], args.author)
			else
				fehler( "Konflikt", "'author*link*' ohne 'author'" )	
			end
		end
    else
    	r = a
    end   
    args.author = r
    return r, etal
end -- Autor()



local Datum = function ( args )
--|date
--|year
    local r = args.year or args.date
    if r then
        if args.year and args.date then
	        fehler( "Doppelt", "'year' und 'date'" )
        elseif args.year and ((tonumber( args.year ) or 0) > 0) then
        	r = args.year
        elseif args.date then
			r = args.date 
			--erweiterte Datumsauswertung, z.B. ISO-Format prüfen?
    	end
    	args.date=r
    end
    return r
end -- Datum()



local Herausgeber = function ( args, max )
-- |editor
-- |editors

-- Noch nicht unterstützt
-- |editor-first |editor-last |editor-link
-- |editor1-last |editor1-first |editor1-link
-- ...
-- |editor5-last |editor5-first |editor5-link
-- |display-editors

    local r = args.editor or args.editors
    local e = hrsgListe( args, max or 5 )
    if r and e then
    	fehler( "Doppelt", "'editor(s)' und 'editor*-last'" )
	elseif r then
        if args.editor and args.editors then
            fehler( "Doppelt", "'editor' und 'editors'" )
        end
    else
    	r = e
    end
    
    if args.series and (not args.chapter and args.title) then
    	args._serieseditor = r
    	args.editor = nil
    else
    	args.editor = r
    end
    
    return r
end -- Herausgeber()



local Seiten = function ( args )
    local r = args.page or args.pages
    if r then
        if args.page and args.pages then
            fehler( "Doppelt", "'page' und 'pages'" )
        end
        -- p. bzw. pp. durch f. bzw. ff. ersetzen
        s = r:gsub( "[%s]*pp[%.]*", " ff." ):gsub( "[%s]*p[%.]*", " f." )
        if r ~= s then
        	fehler( "Wert", "'page' oder 'pages' enthält englischsprachige Abkürzungen" )
    	else
    		r = s
		end
	end
	args.pages = r
    return r
end -- Seiten()



local URL = function ( args )
    local r
    if args.chapter then
    	r = args.chapterurl
    else
		r = args.url
	end
   	args.url= r
	return r
end -- URL()



local Titel = function ( args )
	-- chapter ist dominat. title wird später zu work
    local r = args.chapter or args.title
    if args.chapter then
    	if not args.title then
			fehler( "Wert", "'chapter' ohne 'title'" )	
		end
	end
	args["new.title"] = r
    return r
end -- Titel()



-- Existiert in der Form nicht in den cite-Vorlagen --> Anpassung an WP:ZR
local Werk = function ( args )
    local r
    -- title --> Werk wenn chapter und series vorhanden
    if args.chapter then
    	if args.title then
			r = args.title
		-- Gilt nur für Journale, findet bei books keine Anwendung
		--elseif args.series and not (args.title) then
		--		r = args.series
		end
	else
		-- Gilt nur für Journale, findet bei books keine Anwendung
		--if args.series and not (args.title) then
		--		r = args.series
		--end
	end
	args["new.work"] = r
    return r
end -- Werk()



local format = function ( args )
    -- Analysiere Argumente und bilde formatierte Zitation
    -- Parameter:
    --     args    -- table mit Vorlagenparametern
    -- Rückgabewert: string mit formatierter Zitation
    local pars = Zitation.filter( args, ParValid )
    local r, schrott
    
    --z.Autor, etal = 
    Autor( pars, tonumber(args["display-authors"]) or 9)
    --if etal then
	--	z.Coins_autoren = Autor( pars, 99 )
	--end    
	
	Herausgeber( pars, tonumber(args["display-editors"]) )    	
    Datum( pars )
    Titel( pars )
    Werk( pars )
    URL( pars )
    
    --pars.Klasse = "book"
   
    Zitation.filler( pars, ParMap )
    if Zitation.o then
        Zitation.fill( "leise",  "leiser",   true )
        Zitation.fill( "leise",  "Vorlage",  pars.Vorlage or Selbst )
        if not schrott then
            Zitation.o.coins = true
        end
    end
    r, schrott = Zitation.format()
    if schrott then
        r = r .. Zitation.fault( schrott )
    end
    return r
end -- format()



local function f( arglist, frame )
    -- Hauptfunktion zur Steuerung des Gesamtablaufs
    -- Parameter:
    --     arglist  -- table, mit Vorlagenparametern
    --     frame    -- object, oder nil
    -- Rückgabewert: string mit formatiertem Gesamtergebnis
    --                      einschließlich Fehlerliste und Kategorien
    local lucky, r = pcall( require, "Modul:Zitation" )
    if type( r ) == "table" then
        Zitation       = r.Zitation()
        Zitation.frame = frame
        r              = format( arglist )
    else
        fehler( "Modul", r )
    end
    return r .. fehlerliste()
end -- f()



-- Export
local p = {}

function p.test( a )
    local lucky, r = pcall( f, a )
    return r
end

function p.f( frame )
    local lucky, r = pcall( f, frame:getParent().args, frame )
    return r
end

return p