#-*- coding: utf-8 -*-
# (c) 2012-2013 Anders Andersen
# See http://www.cs.uit.no/~aa/dist/tools/py/COPYING for details
import sys
import json


# The common data about publications:
#
# - mypubl["forskningsresultat"][]["fellesdata"]
#	["tittel"] -> title
#	["person"][]["fornavn"] -> author first name
#	["person"][]["etternavn"] -> author last name
#	["ar"] -> year
#	["kategori"]["hovedkategori"]["navnEngelsk"] -> main category
#	["kategori"]["underkategori"]["navnEngelsk"] -> sub category

commonmap = {
    "tittel": "title",
    "person": {"authors": {"fornavn": "fname", "etternavn": "lname", "tilhorighet": "more"}},
    "ar": "year",
    "ressurs": {"ref": {"type": "kode", "url": "url"}},
    ("kategori","hovedkategori","navnEngelsk") : "mcat",
    ("kategori","underkategori","navnEngelsk") : "scat",
    ("rapportdata", "publikasjonskanal", "serie", "navn") : "journal",
    ("rapportdata", "publikasjonskanal", "serie", "issn") : "issn",
    ("rapportdata", "publikasjonskanal", "hefte") : "no"
}


# The different type of publications (identified so far):
#
# - mypubl["forskningsresultat"][]["kategoridata"]["mediebidrag"]
#	["medium"] -> url
#
# - mypubl["forskningsresultat"][]["kategoridata"]["foredragPoster"]
#	["arrangement"]["tittel"] -> conference name
#	["arrangement"]["sted"] -> address/location
#	["arrangement"]["arrangor"] -> organizer
#
# - mypubl["forskningsresultat"][]["kategoridata"]["bokRapport"]
#	["utgiver","forlag"]["navn"] -> proceeding/book/publisher
#	["utgiver","forlag"]["sted"] -> address/location
#	["utgiver","forlag"]["isbn"] -> isbn
#
# - mypubl["forskningsresultat"][]["kategoridata"]["bokRapportDel"]
#	["delAv"]["forskningsresultat"]["fellesdata"]["tittel"] -> proceeding/book
#	["delAv"]["forskningsresultat"]["kategoridata"]["bokRapport"] -> bokRapport (above)
#
# - mypubl["forskningsresultat"][]["kategoridata"]["tidsskriftsartikkel"]
#	["tidsskrift"]["navn"] -> publication/journal
#	["tidsskrift"]["issn"] -> issn
#	["volum"] -> vol
#	["hefte"] -> no
#	["sideangivelse"]["sideFra"] -> from page
#	["sideangivelse"]["sideTil"] -> to page

catmap = {
    "mediebidrag": {
        "medium": "media",
        ("mediumtype", "navnEngelsk"): "type",
    },
    "foredragPoster": {
        ("arrangement", "tittel") : "booktitle",
        ("arrangement", "sted") : "address",
        ("arrangement", "arrangor") : "organizer",
    },
    "bokRapport": {
        ("utgiver", "navn"): "booktitle",
        ("utgiver", "sted"): "address",
        ("forlag", "navn"): "booktitle",
        ("forlag", "sted"): "address",
        "isbn": "isbn",
        "hefte": "no",
        "volum": "vol",
    },
    "bokRapportDel": {
        ("delAv", "forskningsresultat", "fellesdata", "tittel") : "chaptitle",
        ("delAv", "forskningsresultat", "kategoridata", "bokRapport") : "bokRapport",
    },
    "tidsskriftsartikkel": {
        ("tidsskrift", "navn"): "journal",
        ("tidsskrift", "issn"): "issn",
        "volum": "vol",
        "hefte": "no",
        ("sideangivelse", "sideFra"): "from",
        ("sideangivelse", "sideTil"): "to",
    },
}

# The order the information is presented
order = ["chaptitle", "booktitle", "media", "type", "journal", "vol", "no", "organizer",
             "address", "year", "from", "to", "issn", "isbn"]

# Mapping of type of publication (the value should match a name in 'porder')
tmap = {
    ("mediebidrag", "Media contribution", "Interview"): "Media contributions",
    ("mediebidrag", "Media contribution", "Programme participation"): "Media contributions",
    ("", "Information material(s)", "Website (informational material)"): "Web pages",
    ("foredragPoster", "Conference lecture and academic presentation", "Popular scientific lecture"): "Popular scientific presentations",
    ("foredragPoster", "Conference lecture and academic presentation", "Poster"): "Posters",
    ("foredragPoster", "Conference lecture and academic presentation", "Academic lecture"): "Conference presentations",
    ("tidsskriftsartikkel", "Journal publication", "Academic article"): "Journal publications",
    ("bokRapport", "Report/thesis", "Report"): "Technical reports",
    ("bokRapport", "Report/thesis", "Masters thesis"): "Master student thesises",
    ("bokRapport", "Report/thesis", "Doctoral dissertation"): "PhD student thesises",
    ("bokRapport", "Report/thesis", "Thesis at a second degree level"): "Master student thesises",
    ("bokRapportDel", "Part of a book/report", "Academic chapter/article"): "Conference publications"
}

# The order the publications are presented
porder = [
    "Journal publications",
    "Conference publications",
    "Conference presentations",
    "Posters",
    "Thesises",
    "Technical reports",
    "Popular scientific presentations",
    "Web pages",
    "Media contributions",
    "Interviews",
    "PhD student thesises",
    "Master student thesises"]

# Write out a warning message to stderr
def warning(msg, pre="Warning: "):
    sys.stderr.write("%s%s\n" % (pre, msg))
    sys.stderr.flush()

# Remove trailing punctation in string
def stripit(txt):
    if type(txt) is str:
        if len(txt) > 0:
            if txt[-1] in (',', '.'):
                return txt[:-1]
    return txt

# Fetch data from indata based on map
def getit(indata, map):

    # Returns a ditionary with selected info
    outdata = {}

    # The map is the info we searching for
    for k in map:

        # Go to correct level in indata for this info
        v = None
        if type(k) is tuple:
            v = indata
            for kk in k:
                if kk in v: v = v[kk]
                else: v = None; break

        # Upper level is OK
        elif k in indata:
            v = indata[k]

        # Key k not used in this document (no error)
        else:
            pass # warning("No %s in this publication" % (repr(k)))

        # Then map the data
        if v:

            # A single element
            if type(map[k]) is str:

                # Recursive, the element is another category
                if map[k] in catmap:
                    outdata.update(getit(v, catmap[map[k]]))
                    
                # A simple get str value from indata with new key
                else:
                    outdata[map[k]] = stripit(v)

            # Possible a list
            elif type(map[k]) is dict:

                # Only one iteration of this loop (fetch the new key for the list)
                for kk in map[k]:

                    # If indata is not a list, make it a list (with one element)
                    if type(v) is list:
                        alist = v
                    else:
                        alist = [v]

                    # Produce list
                    outdata[kk] = []
                    for n in alist:
                        ndict = {}
                        for kkk in map[k][kk]:
                            ndict[map[k][kk][kkk]] = stripit(n[kkk])
                        outdata[kk].append(ndict)

            # Unknown
            else:
                warning("unknown key type %s" % (str(type(map[k]))))
        
        # No match (no error)
        else:
            pass # warning("%s not in data" % (k,))
                        
    # Return selected info
    return outdata

# Add entry to publication list
def addit(publist, category, entry):
    if not category in publist:
        publist[category] = [entry.decode()]
    else:
        publist[category].append(entry.decode())
