#!/usr/bin/env python3
"""
Project Trellis Master HTML Generation Script

Usage:
html_all.py <output_folder>
"""

import os, sys, time
from os import path
from string import Template
import argparse
import database
import html_tilegrid
import html_bits
import fuzzloops
import pytrellis
import cell_html
import timing_dbs
import interconnect_html

trellis_docs_index = """
<html>
<head>
<title>Project Trellis HTML Documentation</title>
</head>
<body>
<h1>Project Trellis HTML Documentation</h1>
<p>Project Trellis is a project to document the ECP5 bitstream and internal architecture.</p>
<p>This repository contains HTML documentation automatically generated from the
<a href="https://github.com/YosysHQ/prjtrellis">Project Trellis</a> database. The equivalent
machine-readable data is located in <a href="https://github.com/YosysHQ/prjtrellis-db">prjtrellis-db.<a/>
Data generated includes tilemap data and bitstream data for many tile types. Click on any tile to see its bitstream
documentation.
</p>

<p>More human-readable documentation on the ECP5 architecture and the Project Trellis methodology can be found
on the <a href="http://prjtrellis.readthedocs.io/en/latest/">Read the Docs</a> site.</p>

<p>This HTML documentation was generated at ${datetime} from prjtrellis-db commit
<a href="https://github.com/YosysHQ/prjtrellis-db/tree/${commit}">${commit}</a>.</p>
<hr/>
$docs_toc
<hr/>
<p>Licensed under a very permissive <a href="COPYING">CC0 1.0 Universal</a> license.</p>
</body>
</html>
"""

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('fld', type=str,
                    help="output folder")


def generate_device_docs(family, device, folder):
    html_tilegrid.main(["html_tilegrid", family, device, path.join(folder, "index.html")])


def generate_tile_docs(family, device, tile, folder):
    html_bits.main(["html_bits", family, device, tile, path.join(folder, "{}.html".format(tile))])


def get_device_tiles(family, devices):
    all_tiles = set()
    fd_tiles = {}
    for dev, devdata in sorted(devices.items()):
        if devdata["fuzz"]:
            fd_tiles[family, dev] = []
            c = pytrellis.Chip(dev)
            for tile in c.get_all_tiles():
                tt = tile.info.type
                if tt not in all_tiles:
                    all_tiles.add(tt)
                    fd_tiles[family, dev].append(tt)
    return fd_tiles


def main(argv):
    args = parser.parse_args(argv[1:])
    if not path.exists(args.fld):
        os.mkdir(args.fld)
    commit_hash = database.get_db_commit()
    build_dt = time.strftime('%Y-%m-%d %H:%M:%S')
    docs_toc = ""
    pytrellis.load_database(database.get_db_root())
    for fam, fam_data in sorted(database.get_devices()["families"].items()):
        fdir = path.join(args.fld, fam)
        if not path.exists(fdir):
            os.mkdir(fdir)
        thdir = path.join(fdir, "tilehtml")
        if not path.exists(thdir):
            os.mkdir(thdir)
        docs_toc += "<h3>{} Family</h3>".format(fam)
        docs_toc += "<h4>Bitstream Documentation</h4>"
        docs_toc += "<ul>"
        tiles = get_device_tiles(fam, fam_data["devices"])
        for dev, devdata in sorted(fam_data["devices"].items()):
            if devdata["fuzz"]:
                ddir = path.join(fdir, dev)
                if not path.exists(ddir):
                    os.mkdir(ddir)
                print("********* Generating documentation for device {}".format(dev))
                generate_device_docs(fam, dev, ddir)
                if (fam, dev) in tiles:
                    for tile in tiles[fam, dev]:
                        print("*** Generating documentation for tile {}".format(tile))
                        generate_tile_docs(fam, dev, tile, thdir)
                docs_toc += '<li><a href="{}">{} Documentation</a></li>'.format(
                    '{}/{}/index.html'.format(fam, dev),
                    dev
                )
        docs_toc += "</ul>"

        # No timing stuff for MachXO2 yet.
        if fam in ["ECP5"]:
            docs_toc += "<h4>Cell Timing Documentation</h4>"
            docs_toc += "<ul>"
            for spgrade in ["6", "7", "8", "8_5G"]:
                tdir = path.join(fdir, "timing")
                if not path.exists(tdir):
                    os.mkdir(tdir)
                docs_toc += '<li><a href="{}">Speed Grade -{}</a></li>'.format(
                    '{}/timing/cell_timing_{}.html'.format(fam, spgrade),
                    spgrade
                )
                cell_html.make_cell_timing_html(timing_dbs.cells_db_path(fam, spgrade), fam, spgrade,
                                                path.join(tdir, 'cell_timing_{}.html'.format(spgrade)))
            docs_toc += "</ul>"
            docs_toc += "<h4>Interconnect Timing Documentation</h4>"
            docs_toc += "<ul>"
            for spgrade in ["6", "7", "8", "8_5G"]:
                tdir = path.join(fdir, "timing")
                if not path.exists(tdir):
                    os.mkdir(tdir)
                docs_toc += '<li><a href="{}">Speed Grade -{}</a></li>'.format(
                    '{}/timing/interconn_timing_{}.html'.format(fam, spgrade),
                    spgrade
                )
                interconnect_html.make_interconn_timing_html(timing_dbs.interconnect_db_path(fam, spgrade), fam, spgrade,
                                                path.join(tdir, 'interconn_timing_{}.html'.format(spgrade)))
            docs_toc += "</ul>"

    index_html = Template(trellis_docs_index).substitute(
        datetime=build_dt,
        commit=commit_hash,
        docs_toc=docs_toc
    )
    with open(path.join(args.fld, "index.html"), 'w') as f:
        f.write(index_html)


if __name__ == "__main__":
    main(sys.argv)
