/*
 * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package build.tools.jigsaw;

import java.io.IOException;
import java.io.PrintStream;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static java.lang.module.ModuleDescriptor.*;
import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Selector.*;
import static build.tools.jigsaw.ModuleSummary.HtmlDocument.Division.*;

public class ModuleSummary {
    private static final String USAGE = "Usage: ModuleSummary --module-path <dir> -o <outfile> [--root mn]*";

    public static void main(String[] args) throws Exception {
        int i=0;
        Path modpath = null;
        Path outfile = null;
        Set<String> roots = new HashSet<>();
        while (i < args.length && args[i].startsWith("-")) {
            String arg = args[i++];
            switch (arg) {
                case "--module-path":
                    modpath = Paths.get(args[i++]);
                    break;
                case "-o":
                    outfile = Paths.get(args[i++]);
                    break;
                case "--root":
                    roots.add(args[i++]);
                default:
                    System.err.println(USAGE);
                    System.exit(-1);
            }
        }
        if (outfile == null || modpath == null) {
            System.err.println(USAGE);
            System.exit(1);
        }
        Path dir = outfile.getParent() != null ? outfile.getParent() : Paths.get(".");
        Files.createDirectories(dir);

        Map<String, ModuleSummary> modules = new HashMap<>();
        Set<ModuleReference> mrefs = ModuleFinder.ofSystem().findAll();
        for (ModuleReference mref : mrefs) {
            String mn = mref.descriptor().name();
            Path jmod = modpath.resolve(mn + ".jmod");
            modules.put(mn, new ModuleSummary(mref, jmod));
        }

        if (roots.isEmpty()) {
            roots.addAll(modules.keySet());
        }
        genReport(outfile, modules, roots, "JDK Module Summary");
    }

    static void genReport(Path outfile, Map<String, ModuleSummary> modules, Set<String> roots, String title)
        throws IOException
    {
        Configuration cf = resolve(roots);
        try (PrintStream out = new PrintStream(Files.newOutputStream(outfile))) {
            HtmlDocument doc = new HtmlDocument(title, modules);
            Set<ModuleDescriptor> descriptors = cf.modules().stream()
                    .map(ResolvedModule::reference)
                    .map(ModuleReference::descriptor)
                    .collect(Collectors.toSet());
            doc.writeTo(out, descriptors);
        }
    }

    private final String name;
    private final ModuleDescriptor descriptor;
    private final JmodInfo jmodInfo;
    ModuleSummary(ModuleReference mref, Path jmod) throws IOException {
        this.name = mref.descriptor().name();
        this.descriptor = mref.descriptor();
        this.jmodInfo = new JmodInfo(jmod);
    }

    String name() {
        return name;
    }

    long uncompressedSize() {
        return jmodInfo.size;
    }

    long jmodFileSize() {
        return jmodInfo.filesize; // estimated compressed size
    }

    ModuleDescriptor descriptor() {
        return descriptor;
    }

    int numClasses() {
        return jmodInfo.classCount;
    }

    long classBytes() {
        return jmodInfo.classBytes;
    }

    int numResources() {
        return jmodInfo.resourceCount;
    }

    long resourceBytes() {
        return jmodInfo.resourceBytes;
    }

    int numConfigs() {
        return jmodInfo.configCount;
    }
    long configBytes() {
        return jmodInfo.configBytes;
    }
    int numCommands() {
        return jmodInfo.nativeCmds.size();
    }

    long commandBytes() {
        return jmodInfo.nativeCmds.values().stream()
                .mapToLong(l -> l.longValue()).sum() - jmodInfo.debugInfoCmdBytes;
    }
    int numCommandsDebug() {
        return jmodInfo.debugInfoCmdCount;
    }
    long commandDebugBytes() {
        return jmodInfo.debugInfoCmdBytes;
    }
    int numNativeLibraries() {
        return jmodInfo.nativeLibs.size();
    }

    long nativeLibrariesBytes() {
        return jmodInfo.nativeLibs.values().stream()
                .mapToLong(l -> l.longValue()).sum() - jmodInfo.debugInfoLibBytes;
    }
    int numNativeLibrariesDebug() {
        return jmodInfo.debugInfoLibCount;
    }

    long nativeLibrariesDebugBytes() {
        return jmodInfo.debugInfoLibBytes;
    }

    Map<String,Long> commands() {
        return jmodInfo.nativeCmds;
    }

    Map<String,Long> nativeLibs() {
        return jmodInfo.nativeLibs;
    }

    Map<String,Long> configFiles() {
        return jmodInfo.configFiles;
    }


    static class JmodInfo {
        final long size;
        final long filesize;
        final int  classCount;
        final long classBytes;
        final int  resourceCount;
        final long resourceBytes;
        final int  configCount;
        final long configBytes;
        final int  debugInfoLibCount;
        final long debugInfoLibBytes;
        final int  debugInfoCmdCount;
        final long debugInfoCmdBytes;
        final Map<String,Long> configFiles = new HashMap<>();
        final Map<String,Long> nativeCmds = new HashMap<>();
        final Map<String,Long> nativeLibs = new HashMap<>();

        JmodInfo(Path jmod) throws IOException {
            long total = 0;
            long cBytes = 0, rBytes = 0, cfBytes = 0, dizLibBytes = 0, dizCmdBytes = 0;
            int  cCount = 0, rCount = 0, cfCount = 0, dizLibCount = 0, dizCmdCount = 0;
            try (ZipFile zf = new ZipFile(jmod.toFile())) {
                for (Enumeration<? extends ZipEntry> e = zf.entries(); e.hasMoreElements(); ) {
                    ZipEntry ze = e.nextElement();
                    String fn = ze.getName();
                    int pos = fn.indexOf('/');
                    String dir = fn.substring(0, pos);
                    String filename = fn.substring(fn.lastIndexOf('/') + 1);
                    // name shown in the column
                    String name = filename;

                    long len = ze.getSize();
                    total += len;
                    switch (dir) {
                        case NATIVE_LIBS:
                            nativeLibs.put(name, len);
                            if (filename.endsWith(".diz")) {
                                dizLibCount++;
                                dizLibBytes += len;
                            }
                            break;
                        case NATIVE_CMDS:
                            nativeCmds.put(name, len);
                            if (filename.endsWith(".diz")) {
                                dizCmdCount++;
                                dizCmdBytes += len;
                            }
                            break;
                        case CLASSES:
                            if (filename.endsWith(".class")) {
                                cCount++;
                                cBytes += len;
                            } else {
                                rCount++;
                                rBytes += len;
                            }
                            break;
                        case CONFIG:
                            configFiles.put(name, len);
                            cfCount++;
                            cfBytes += len;
                            break;
                        default:
                            break;
                    }
                }
                this.filesize = jmod.toFile().length();
                this.classCount = cCount;
                this.classBytes = cBytes;
                this.resourceCount = rCount;
                this.resourceBytes = rBytes;
                this.configCount = cfCount;
                this.configBytes = cfBytes;
                this.size = total;
                this.debugInfoLibCount = dizLibCount;
                this.debugInfoLibBytes = dizLibBytes;
                this.debugInfoCmdCount = dizCmdCount;
                this.debugInfoCmdBytes = dizCmdBytes;
            }
        }

        static final String NATIVE_LIBS = "native";
        static final String NATIVE_CMDS = "bin";
        static final String CLASSES     = "classes";
        static final String CONFIG      = "conf";

        static final String MODULE_ID = "module/id";
        static final String MODULE_MAIN_CLASS = "module/main-class";
    }

    static Configuration resolve(Set<String> roots) {
        return Configuration.empty()
            .resolveRequires(ModuleFinder.ofSystem(),
                             ModuleFinder.of(),
                             roots);
    }

    static class HtmlDocument {
        final String title;
        final Map<String, ModuleSummary> modules;
        boolean requiresTransitiveNote = false;
        boolean aggregatorNote = false;
        boolean totalBytesNote = false;
        HtmlDocument(String title, Map<String, ModuleSummary> modules) {
            this.title = title;
            this.modules = modules;
        }

        void writeTo(PrintStream out, Set<ModuleDescriptor> selectedModules) {
            out.format("<html><head>%n");
            out.format("<title>%s</title>%n", title);
            // stylesheet
            Arrays.stream(HtmlDocument.STYLES).forEach(out::println);
            out.format("</head>%n");

            // body begins
            out.format("<body>%n");

            // title and date
            out.println(DOCTITLE.toString(title));
            out.println(VERSION.toString(String.format("%tc", new Date())));

            // total modules and sizes
            long totalBytes = selectedModules.stream()
                    .map(ModuleDescriptor::name)
                    .map(modules::get)
                    .mapToLong(ModuleSummary::uncompressedSize)
                    .sum();
            String[] sections = new String[] {
                    String.format("%s: %d", "Total modules", selectedModules.size()),
                    String.format("%s: %,d bytes (%s %s)", "Total size",
                                  totalBytes,
                                  System.getProperty("os.name"),
                                  System.getProperty("os.arch"))
            };
            out.println(SECTION.toString(sections));

            // write table and header
            out.println(String.format("<table class=\"%s\">", MODULES));
            out.println(header("Module", "Requires", "Exports",
                    "Services", "Commands/Native Libraries/Configs"));

            // write contents - one row per module
            selectedModules.stream()
                    .sorted(Comparator.comparing(ModuleDescriptor::name))
                    .map(m -> modules.get(m.name()))
                    .map(ModuleTableRow::new)
                    .forEach(table -> table.writeTo(out));

            out.format("</table>");  // end table
            out.format("</body>");
            out.println("</html>");
        }

        String header(String... columns) {
            StringBuilder sb = new StringBuilder();
            sb.append("<tr>");
            Arrays.stream(columns)
                    .forEach(cn -> sb.append("  <th>").append(cn).append("</th>").append("\n"));
            sb.append("</tr>");
            return sb.toString();
        }

        static enum Selector {
            MODULES("modules"),
            MODULE("module"),
            MODULE_DEF("code name def"),
            AGGREGATOR("code name def agg"),
            REQUIRES("code"),
            REQUIRES_PUBLIC("code reexp"),
            BR("br"),
            CODE("code"),
            NUMBER("number"),;
            final String name;
            Selector(String name) {
                this.name = name;
            }
            @Override
            public String toString() {
                return name;
            }
        }

        static enum Division {
            DOCTITLE("doctitle"),
            VERSION("versions"),
            SECTION("section");
            final String name;

            Division(String name) {
                this.name = name;
            }

            public String toString(String... lines) {
                String value = Arrays.stream(lines).collect(Collectors.joining("<br>\n"));
                return "<div class=\"" + name + "\">" + value + "</div>";
            }
        }

        class ModuleTableRow {
            private final ModuleSummary ms;
            private final Set<ModuleDescriptor> deps;
            private final int maxRows;
            private final boolean aggregator;
            ModuleTableRow(ModuleSummary ms) {
                this.ms = ms;
                Configuration cf = resolve(Set.of(ms.name()));
                this.deps = cf.modules().stream()
                        .map(ResolvedModule::reference)
                        .map(ModuleReference::descriptor)
                        .collect(Collectors.toSet());
                int count = (ms.numClasses() > 0 ? 1 : 0) +
                            (ms.numResources() > 0 ? 1 : 0) +
                            (ms.numConfigs() > 0 ? 1 : 0) +
                            (ms.numNativeLibraries() > 0 ? 1 : 0) +
                            (ms.numNativeLibrariesDebug() > 0 ? 1 : 0) +
                            (ms.numCommands() > 0 ? 1 : 0) +
                            (ms.numCommandsDebug() > 0 ? 1 : 0);
                this.aggregator = ms.numClasses() == 1 && count == 1; // only module-info.class

                // 5 fixed rows (name + 2 transitive count/size + 2 blank rows)
                this.maxRows = 5 + count + (aggregator && !aggregatorNote ? 2 : 0);
            }

            public void writeTo(PrintStream out) {
                out.println(String.format("<tr id=\"%s\" class=\"%s\">", ms.name(), MODULE));
                out.println(moduleColumn());
                out.println(requiresColumn());
                out.println(exportsColumn());
                out.println(servicesColumn());
                out.println(otherSectionColumn());
                out.println("</td>");
                out.println("</tr>");
            }

            public String moduleColumn() {
                // module name
                StringBuilder sb = new StringBuilder("  ");
                sb.append("<td>");
                sb.append(String.format("<table class=\"%s\">", MODULE)).append("\n");
                sb.append(moduleName(ms.name()));
                sb.append(blankRow());
                // metadata
                sb.append(toTableRow("class", "classes", ms.numClasses(), ms.classBytes()));
                sb.append(toTableRow("resource", "resources", ms.numResources(), ms.resourceBytes()));
                sb.append(toTableRow("config", "configs", ms.numConfigs(), ms.configBytes()));
                sb.append(toTableRow("native library", "native libraries",
                                     ms.numNativeLibraries(), ms.nativeLibrariesBytes()));
                sb.append(toTableRow("native library debug", "native libraries debug",
                                     ms.numNativeLibrariesDebug(), ms.nativeLibrariesDebugBytes()));
                sb.append(toTableRow("command", "commands", ms.numCommands(), ms.commandBytes()));
                sb.append(toTableRow("command debug", "commands debug",
                                     ms.numCommandsDebug(), ms.commandDebugBytes()));
                sb.append(blankRow());

                // transitive dependencies
                long reqBytes = deps.stream()
                                    .filter(d -> !d.name().equals(ms.name()))
                                    .mapToLong(d -> modules.get(d.name()).uncompressedSize())
                                    .sum();
                long reqJmodFileSize = deps.stream()
                                            .mapToLong(d -> modules.get(d.name()).jmodFileSize())
                                            .sum();
                // size
                if (totalBytesNote) {
                    sb.append(toTableRow("Total bytes", ms.uncompressedSize()));
                    sb.append(toTableRow("Total bytes of dependencies", reqBytes));
                } else {
                    // print footnote
                    sb.append(toTableRow("Total bytes<sup>1</sup>", ms.uncompressedSize()));
                    sb.append(toTableRow("Total bytes of dependencies<sup>2</sup>", reqBytes));
                }
                String files = deps.size() == 1 ? "file" : "files";
                sb.append(toTableRow(String.format("Total jmod bytes (%d %s)", deps.size(), files), reqJmodFileSize));

                if (aggregator && !aggregatorNote) {
                    aggregatorNote = true;
                    sb.append(blankRow());
                    sb.append(toTableRow("<i>* aggregator is a module with module-info.class only</i>", BR));
                }
                if (!totalBytesNote) {
                    totalBytesNote = true;
                    sb.append(blankRow());
                    sb.append(toTableRow("<i><sup>1</sup>sum of all files including debug files</i>", BR));
                    sb.append(toTableRow("<i><sup>2</sup>sum of direct and indirect dependencies</i>", BR));
                }
                sb.append("</table>").append("</td>");
                return sb.toString();
            }

            private String moduleName(String mn) {
                if (aggregator) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(String.format("<tr><td colspan=\"2\"><span class=\"%s\">", AGGREGATOR))
                      .append(mn)
                      .append("</span>").append("&nbsp;&nbsp;");
                    if (!aggregatorNote) {
                        sb.append("(aggregator<sup>*</sup>)");
                    } else {
                        sb.append("(aggregator)");
                    }
                    sb.append("</td></tr>");
                    return sb.toString();
                } else {
                    return toTableRow(mn, MODULE_DEF);
                }
            }

            public String requiresColumn() {
                StringBuilder sb = new StringBuilder();
                sb.append(String.format("<td>"));
                boolean footnote = requiresTransitiveNote;
                ms.descriptor().requires().stream()
                        .sorted(Comparator.comparing(Requires::name))
                        .forEach(r -> {
                            boolean requiresTransitive = r.modifiers().contains(Requires.Modifier.TRANSITIVE);
                            Selector sel = requiresTransitive ? REQUIRES_PUBLIC : REQUIRES;
                            String req = String.format("<a class=\"%s\" href=\"#%s\">%s</a>",
                                                       sel, r.name(), r.name());
                            if (!requiresTransitiveNote && requiresTransitive) {
                                requiresTransitiveNote = true;
                                req += "<sup>*</sup>";
                            }
                            sb.append(req).append("\n").append("<br>");
                        });

                if (!ms.name().equals("java.base")) {
                    int directDeps = ms.descriptor().requires().size();
                    int indirectDeps = deps.size()-directDeps-1;
                    for (int i=directDeps; i< (maxRows-1); i++) {
                        sb.append("<br>");
                    }
                    sb.append("<br>");
                    sb.append("<i>+").append(indirectDeps).append(" transitive dependencies</i>");
                }
                if (footnote != requiresTransitiveNote) {
                    sb.append("<br><br>").append("<i>* bold denotes requires transitive</i>");
                }
                sb.append("</td>");
                return sb.toString();
            }

            public String exportsColumn() {
                StringBuilder sb = new StringBuilder();
                sb.append(String.format("  <td class=\"%s\">", CODE));
                ms.descriptor().exports().stream()
                        .sorted(Comparator.comparing(Exports::source))
                        .filter(e -> !e.isQualified())
                        .forEach(e -> sb.append(e.source()).append("<br>").append("\n"));
                sb.append("</td>");
                return sb.toString();
            }

            public String servicesColumn() {
                StringBuilder sb = new StringBuilder();
                sb.append(String.format("  <td class=\"%s\">", CODE));
                ms.descriptor().uses().stream()
                        .sorted()
                        .forEach(s -> sb.append("uses ").append(s).append("<br>").append("\n"));
                ms.descriptor().provides().stream()
                        .sorted(Comparator.comparing(Provides::service))
                        .map(p -> String.format("provides %s<br>&nbsp;&nbsp;&nbsp;&nbsp;with %s",
                                                p.service(), p.providers()))
                        .forEach(p -> sb.append(p).append("<br>").append("\n"));
                sb.append("</td>");
                return sb.toString();
            }

            public String otherSectionColumn() {
                StringBuilder sb = new StringBuilder();
                sb.append("<td>");
                sb.append(String.format("<table class=\"%s\">", MODULE)).append("\n");
                // commands
                if (ms.numCommands() > 0) {
                    sb.append(toTableRow("bin/", CODE));
                    ms.commands().entrySet().stream()
                            .sorted(Map.Entry.comparingByKey())
                            .forEach(e -> sb.append(toTableRow(e.getKey(), e.getValue(), CODE)));
                    sb.append(blankRow());
                }

                // native libraries
                if (ms.numNativeLibraries() > 0) {
                    sb.append(toTableRow("lib/", CODE));
                    ms.nativeLibs().entrySet().stream()
                            .sorted(Map.Entry.comparingByKey())
                            .forEach(e -> sb.append(toTableRow(e.getKey(), e.getValue(), CODE)));
                    sb.append(blankRow());
                }

                // config files
                if (ms.numConfigs() > 0) {
                    sb.append(toTableRow("conf/", CODE));
                    ms.configFiles().entrySet().stream()
                            .sorted(Map.Entry.comparingByKey())
                            .forEach(e -> sb.append(toTableRow(e.getKey(), e.getValue(), CODE)));
                }
                // totals
                sb.append("</table>").append("</td>");
                return sb.toString();
            }

            private String blankRow() {
                return toTableRow("&nbsp;", BR);
            }

            private String toTableRow(String col, Selector selector) {
                TableDataBuilder builder = new TableDataBuilder();
                builder.colspan(selector, 2, col);
                return builder.build();
            }

            private String toTableRow(String col1, long col2) {
                return toTableRow(col1, col2, BR);
            }

            private String toTableRow(String col1, long col2, Selector selector) {
                TableDataBuilder builder = new TableDataBuilder();
                builder.data(selector, col1);
                builder.data(col2);
                return builder.build();

            }

            private String toTableRow(String singular, String plural, int count, long bytes) {
                if (count == 0) {
                    return "";
                }
                TableDataBuilder builder = new TableDataBuilder();
                if (count == 1) {
                    builder.data(count + " " + singular);
                } else {
                    builder.data(count + " " + plural);
                }
                builder.data(bytes);
                return builder.build();
            }

            class TableDataBuilder {
                private final StringBuilder sb;
                TableDataBuilder() {
                    this.sb = new StringBuilder("<tr>");
                }
                TableDataBuilder data(String s) {
                    data(BR, s);
                    return this;
                }
                TableDataBuilder data(long num) {
                    data(NUMBER, String.format("%,d", num));
                    return this;
                }
                TableDataBuilder colspan(Selector selector, int columns, String data) {
                    sb.append("<td colspan=\"").append(columns).append("\">");
                    sb.append("<span class=\"").append(selector).append("\">");
                    sb.append(data).append("</span></td>");
                    return this;
                }

                TableDataBuilder data(Selector selector, String data) {
                    sb.append("<td class=\"").append(selector).append("\">");
                    sb.append(data).append("</td>");
                    return this;
                }
                String build() {
                    sb.append("</tr>");
                    return sb.toString();
                }
            }
        }

        private static final String[] STYLES = new String[]{
                "<link rel=\"stylesheet\" type=\"text/css\" href=\"/.fonts/dejavu.css\"/>",
                "<style type=\"text/css\">",
                "        HTML, BODY, DIV, SPAN, APPLET, OBJECT, IFRAME, H1, H2, H3, H4, H5, H6, P,",
                "        BLOCKQUOTE, PRE, A, ABBR, ACRONYM, ADDRESS, BIG, CITE, CODE, DEL, DFN, EM,",
                "        IMG, INS, KBD, Q, S, SAMP, SMALL, STRIKE, STRONG, SUB, SUP, TT, VAR, B, U,",
                "        I, CENTER, DL, DT, DD, OL, UL, LI, FIELDSET, FORM, LABEL, LEGEND, TABLE,",
                "        CAPTION, TBODY, TFOOT, THEAD, TR, TH, TD, ARTICLE, ASIDE, CANVAS, DETAILS,",
                "        EMBED, FIGURE, FIGCAPTION, FOOTER, HEADER, HGROUP, MENU, NAV, OUTPUT, RUBY,",
                "        SECTION, SUMMARY, TIME, MARK, AUDIO, VIDEO {",
                "          margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit;",
                "          vertical-align: baseline; }",
                "        ARTICLE, ASIDE, DETAILS, FIGCAPTION, FIGURE, ",
                "        FOOTER, HEADER, HGROUP, MENU, NAV, SECTION { display: block; }",
                "        BLOCKQUOTE, Q { quotes: none; }",
                "        BLOCKQUOTE:before, BLOCKQUOTE:after, Q:before, Q:after {",
                "                content: ''; content: none; }",
                "        TABLE { border-collapse: collapse; border-spacing: 0; }",
                "        A { text-decoration: none; }",
                "        A:link { color: #437291; }",
                "        A:visited { color: #666666; }",
                "        A.anchor:link, A.anchor:visited { color: black; }",
                "        A[href]:hover { color: #e76f00; }",
                "        A IMG { border-width: 0px; }",
                "        HTML { font-size: 20px; } /* baseline grid */",
                "        HTML > BODY { font-size: 14px; }",
                "        BODY {",
                "          background: white;",
                "          margin: 40px;",
                "          margin-bottom: 150%;",
                "          line-height: 20px;",
                "          -webkit-text-size-adjust: 100%; /* iOS */",
                "          color: #222;",
                "        }",
                "        BODY { font-family: \"DejaVu Serif\", \"Lucida Bright\", \"Bookman Old Style\",",
                "                            Georgia, serif; }",
                "        CODE, TT, .jref, DIV.spec .open, TABLE.profiles {",
                "          font-family: \"DejaVu Sans\", \"Lucida Sans\", Helvetica, sans-serif; }",
                "        PRE, .code { font-family: \"DejaVu Sans Mono\", \"Bitstream Vera Sans Mono\",",
                "                            Monaco, \"Courier New\", monospace; }",
                "        H1, H2, H3, H4 { color: green; font-weight: bold; }",
                "        I { font-style: italic; }",
                "        TH { font-weight: bold; }",
                "        P { text-indent: 40px; }",
                "        P:first-child, UL + P, OL + P, BLOCKQUOTE + P, TABLE + P, P.subsection,",
                "          P.break, DIV.profiles-table + P { text-indent: 0; }",
                "        P.break { margin-top: 10px; }",
                "        P.subsection { margin-top: 20px; }",
                "        P.subsection SPAN.title { font-weight: bold; padding-right: 20px; }",
                "        UL, OL { margin: 10px 0; padding-left: 40px; }",
                "        LI { margin-bottom: 10px; }",
                "        UL.compact LI { margin-bottom: 0; }",
                "        PRE { padding: 0; margin: 10px 0 10px 20px; background: #eee; width: 45em; }",
                "        BLOCKQUOTE { margin: 10px 0; margin-left: 20px; }",
                "        LI BLOCKQUOTE { margin-left: 0; }",
                "        UL LI { list-style-type: square; }",
                "        .todo { color: darkred; text-align: right; }",
                "        .error { color: red; font-weight: bold; }",
                "        .warn { color: #ee0000; font-weight: bold; }",
                "        DIV.doctitle { margin-top: -13px;",
                "          font-size: 22px; line-height: 40px; font-weight: bold; }",
                "        DIV.twarn { color: #cc0000; font-weight: bold; margin-bottom: 9px; }",
                "        DIV.subtitle { margin-top: 2px; font-size: 18px; font-weight: bold; }",
                "        DIV.authors { margin-top: 10px; margin-bottom: 10px; font-size: 16px; }",
                "        DIV.author A { font-style: italic; }",
                "        DIV.version { margin-top: 10px; font-size: 12px; }",
                "        DIV.version, DIV.legal-notice { font-size: 12px; line-height: 15px; }",
                "        SPAN.hash { font-size: 9px; }",
                "        DIV.version SPAN.modified { color: green; font-weight: bold; }",
                "        DIV.head { margin-bottom: 20px; }",
                "        DIV.section > DIV.title, DIV.section DIV.number SPAN {",
                "          font-size: 15px; font-weight: bold; }",
                "        TABLE { border-collapse: collapse; border: none; }",
                "        TD.number { text-align: right; }",
                "        TD, TH { text-align: left; white-space: nowrap; }",
                "        TD.name, SPAN.name { font-weight: bold; }",
                "        ",
                "        TABLE.module { width: 100%; }",
                "        TABLE.module TD:first-child { padding-right: 10px; }",
                "        TR.module > TD { padding: 10px 0; border-top: 1px solid black; }",
                "        TR > TH { padding-bottom: 10px; }",
                "        TR.br TD { padding-top: 20px; }",
                "        TABLE.modules { margin-top: 20px; }",
                "        TABLE.modules > TBODY > TR > TD:nth-child(even) { background: #eee; }",
                "        TABLE.modules > TBODY > TR > TD, TABLE.modules > TBODY > TR > TH {",
                "          padding-left: 10px; padding-right: 10px; }",
                "        .reexp, .def { font-weight: bold; }",
                "        .agg { font-style: italic; }",
                "        SUP { height: 0; line-height: 1; position: relative;",
                "              vertical-align: baseline; bottom: 1ex; font-size: 11px; }",
                "</style>",
        };
    }
}
