#! /usr/bin/env python3

"""\
Generate an HTML file / directory structure listing available analyses and their metadata
"""

## Parse arguments
import argparse
ap = argparse.ArgumentParser(usage=__doc__)
ap.add_argument("OUTNAME", nargs="?", default="analyses", help="name (minus extension) to give to the output files and dirs")
ap.add_argument("--embed", dest="EMBED", action="store_true", default=False, help="do not generate <html>, <head>, and <body> surrounding tags")
ap.add_argument("--hugo", dest="HUGO", action="store_true", default=False, help="add frontmatter etc. for use in Hugo web pages")
args = ap.parse_args()
if args.HUGO:
    args.EMBED = True

import rivet
import sys, os, re

## Add info file locations
from glob import glob
dirpatt = os.path.join(os.getcwd(), "..", "..", "analyses", "plugin*")
for d in glob(dirpatt):
    rivet.addAnalysisDataPath(os.path.abspath(d))


## Get some strings of HTML ready.
from rivet.util import htmlify
foot = """\
</body>
</html>
"""
head = '''\
<html>
<head>
  <title>Rivet analyses reference</title>
  <style>
    /* body { font-family:sans-serif; padding: 1em 1em 2em 2em; } */
    p, li { max-width:50em; }
    /* h2 { margin-left:-1em; margin-bottom:1.5em; } */
    /* h3 { color:#349; margin-top:2em; } */
  </style>
  <meta charset="utf-8">
  <script type="text/x-mathjax-config">MathJax.Hub.Config({ tex2jax: {inlineMath: [['$','$']]}, inTabOrder: false });</script>
  <script async="async" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML"></script>
</head>
<body>
  <h2>Rivet analyses reference</h2>
'''


## Build analysis pages
can_analyses = rivet.AnalysisLoader.analysisNames()
all_analyses = rivet.AnalysisLoader.allAnalysisNames()
aliases = rivet.AnalysisLoader.analysisNameAliases()
invaliases = {}
for ali, can in aliases.items():
    invaliases.setdefault(can, [])
    invaliases[can].append(ali)

## Remove any existing directory with name OUTDIR, make new one.
OUTFILE = f"{args.OUTNAME}.html"
OUTDIR = args.OUTNAME
if os.path.exists(OUTDIR) and not os.path.realpath(OUTDIR) == os.getcwd():
    import shutil
    shutil.rmtree(OUTDIR)
try:
    os.makedirs(OUTDIR)
except:
    print("Error: failed to make new directory '%s'" % OUTDIR)
    sys.exit(1)

## Find analysis source files
ccpatt = os.path.join(os.getcwd(), "..", "..", "analyses", "plugin*", "*.cc")
ccfiles = glob(ccpatt)
#print(ccfiles)

summaries = {}
reentries = {}
pages = []

## Generate full-detail metadata + code page for canonical names only
for aname in can_analyses:
    page = ""

    ## Title
    page += f"<h3 id='{aname}'>{aname}</h3>\n"

    ## Summary and biblio links
    ana = rivet.AnalysisLoader.getAnalysis(aname)
    summaries[aname] = ana.summary()
    reentries[aname] = ana.reentrant()
    page += "<b>%s</b><br/>\n" %  htmlify(ana.summary())
    page += "<b>Experiment:</b> %s (%s)<br/>\n" % (ana.experiment(), ana.collider())
    if ana.inspireId():
        url = "https://inspirehep.net/literature/{}".format(ana.inspireId())
        page += "<b>Inspire ID:</b> <a href='%s'>%s</a><br/>\n" % (url, ana.inspireId())
    elif ana.spiresId():
        url = "https://inspirehep.net/literature?q={}".format(ana.spiresId())
        page += "<b>Spires ID:</b> <a href='%s'>%s</a><br/>\n" % (url, ana.spiresId())
    page += "<b>Status:</b> %s<br/>\n" % ana.status()

    ## Authors
    if ana.authors():
        page += "<b>Authors:</b>\n"
        page += "<ul>\n"
        for a in ana.authors():
            s = a
            import re
            if re.search(".* <.*@.*>", a):
                name = " ".join(a.split()[:-1])
                email = a.split()[-1].replace("<", "").replace(">", "")
                #s = "<a href='mailto:%s'>%s</a>" % (email, name)
                s = name
            page += "  <li>%s</li>\n" % htmlify(s)
        page += "</ul>\n"
    else:
        page += "<b>No authors listed</b>\n"

    ## References
    if ana.references():
        page += "<b>References:</b>\n"
        page += "<ul>\n"
        for r in ana.references():
            if r.startswith("arXiv:"):
                code = r.split()[0].replace("arXiv:", "")
                url = "http://arxiv.org/abs/" + code
                page += "  <li>%s <a href='%s'>%s</a></li>\n" % ("arXiv:", htmlify(url), htmlify(code))
            elif r.startswith("doi:"):
                code = r.replace("doi:", "")
                url = "https://dx.doi.org/" + code
                page += "  <li>%s <a href='%s'>%s</a></li>\n" % ("DOI:", htmlify(url), htmlify(code))
            elif r.startswith("ALICE-"):
                code = r.replace("ALICE-", "")
                url = "https://alice-publications.web.cern.ch/node/" + code
                page += "  <li>%s <a href='%s'>%s</a></li>\n" % ("Public page:", htmlify(url), htmlify(r))
            elif r.startswith("ATLAS-"):
                code = r.replace("ATLAS-", "")
                url = "https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/PAPERS/" + code
                page += "  <li>%s <a href='%s'>%s</a></li>\n" % ("Public page:", htmlify(url), htmlify(r))
            elif r.startswith("CMS-"):
                code = r.replace("CMS-", "")
                url = "https://cms-results.web.cern.ch/cms-results/public-results/publications/" + code
                page += "  <li>%s <a href='%s'>%s</a></li>\n" % ("Public page:", htmlify(url), htmlify(r))
            elif r.startswith("LHCb-"):
                code = r.replace("PAPER-", "")
                url = "https://lhcbproject.web.cern.ch/Publications/LHCbProjectPublic/%s.html" % r
                page += "  <li>%s <a href='%s'>%s</a></li>\n" % ("Public page:", htmlify(url), htmlify(code))
            else:
                page += "  <li>%s</li>\n" % htmlify(r)
        page += "</ul>\n"
    else:
        page += "<b>No references listed</b><br/>\n"

    ## Beams
    if ana.requiredBeamIDs():
        def pid_to_str(pid):
            if pid == 11:
                return "e-"
            elif pid == -11:
                return "e+"
            elif pid == 2212:
                return "p+"
            elif pid == -2212:
                return "p-"
            elif pid == 10000:
                return "*"
            else:
                return str(pid)
        beamstrs = []
        for bp in ana.requiredBeamIDs():
            beamstrs.append(pid_to_str(bp[0]) + " " + pid_to_str(bp[1]))
        page += "<b>Beams:</b> %s<br/>\n" % ", ".join(beamstrs)

    page += "<b>Beam energies:</b> "
    if ana.requiredBeamEnergies():
        page += "; ".join(["(%0.1f, %0.1f)" % (epair[0], epair[1]) for epair in ana.requiredBeamEnergies()])
        page += "&nbsp;GeV"
    else:
        page += "ANY"
    page += "<br/>\n"

    ## Run info
    if ana.runInfo():
        page += "<b>Run details:</b>\n"
        page += "<ul>\n"
        for l in ana.runInfo().split("\n*"):
            l = l.strip()
            if l.startswith("*"):
                l = l[1:].strip()
            page += "  <li>%s</li>\n" % htmlify(l)
        page += "</ul>\n"
    else:
        page += "<ul>No run details listed</ul>\n"

    ## Description
    page += "\n<p>" + htmlify(ana.description(), para=True) + "</p>\n"

    ## Source code
    anaccfiles = [cc for cc in ccfiles if os.path.basename(cc).startswith(aname)]
    exactanaccfiles = [cc for cc in ccfiles if os.path.basename(cc) == aname+".cc"]
    if exactanaccfiles:
        anaccfiles = exactanaccfiles
    if anaccfiles:
        page += "<b>Source code:</b>\n"
        for cc in anaccfiles:
            page += "<b><kbd>%s</kbd></b>\n" % os.path.basename(cc)
            with open(cc, 'r') as f:
                src = f.read()
                if type(u'') != str:
                    src = src.decode("UTF-8")
            try:
                import pygments
                from pygments.lexers import get_lexer_by_name
                from pygments.formatters import get_formatter_by_name
                lx = get_lexer_by_name("c++")
                fm = get_formatter_by_name("html", linenos="inline", noclasses=True)
                page += pygments.highlight(src, lx, fm)
            except:
                page += "<kbd>" + src.replace("\n", "<br/>\n") + "</kbd>"

    ## Aliases
    if aname in invaliases:
        page += "<b>Aliases:</b>\n"
        page += "<ul>\n"
        for ali in invaliases[aname]:
            page += "  <li>%s</li>\n" % htmlify(ali)
        page += "</ul>\n"

    ## Write out to HTML analysis file
    ANAFILE = os.path.join(OUTDIR, aname+'.html')
    with open(ANAFILE, "wb") as f:
        outstr = page if args.EMBED else (head + page + foot)
        if args.HUGO:
            outstr = f"---\ntitle: {aname}\n---\n" + outstr
        f.write(outstr.encode("UTF-8"))


## Make an HTML table of contents
toc = "<h3>Contents</h3>\n"
toc += "<p>&reg; = analysis supports re-entrant finalize</p>\n"
toc += "<ul style=\"white-space: nowrap;\">\n"
for a in can_analyses:
    ## NB. initial links designed for linking from inside the OUTDIR
    summ = "No summary"
    key = a if a in summaries else aliases[a]
    summ = htmlify(summaries[key])
    if reentries[key]:
        # print(a + " = REENTRANT")
        summ = "&reg;&nbsp;" + summ
        # summ = "R&nbsp;" + summ
    toc += '<li><a id="%s" href="../%s/%s.html">%s</a> &ndash; %s</li>\n' % (a, OUTDIR, a, a, summ)
toc += "</ul>\n"

## Write out the TOC(s)
outstr = toc if args.EMBED else (head + toc + foot)
if args.HUGO:
    outstr = f"---\ntitle: Rivet analysis index\n---\n" + outstr
## In-dir index
with open(os.path.join(OUTDIR, "index.html"), "wb") as f:
    f.write(outstr.encode("UTF-8"))
## External index
outstr = outstr.replace(f"../{OUTDIR}", OUTDIR) #< correct link depth
if OUTFILE == "-":
    sys.stdout.write(outstr.encode("UTF-8"))
else:
    with open(OUTFILE, "wb") as f:
        f.write(outstr.encode("UTF-8"))
