#!/usr/bin/env fuchsia-vendored-python
#
# Copyright 2022 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import functools
import re
import sys

from digest import Digest
from snapshot import Snapshot

group_specs = [
    ["[scudo]", "scudo:.*"],
    ["[relro]", "relro:.*"],
    ["[stacks]", "thrd_t:0x.*|initial-thread|pthread_t:0x.*"],
    ["[data]", "data[0-9]*:.*"],
    ["[blobs]", "blob-[0-9a-f]+"],
    ["[inactive-blobs]", "inactive-blob-[0-9a-f]+"],
    ["[mrkls]", "mrkl-[0-9a-f]+"],
    ["[uncompressed-bootfs]", "uncompressed-bootfs"],
]

for gs in group_specs:
    gs[1] = re.compile(gs[1])


def output_html(buckets):
    nodes = []
    node_id = 1
    snaphot_name = "Snapshot"
    for b in buckets:
        if b.size == 0:
            continue
        nodes.append([b.name, snaphot_name, 0])
        for processes, vmos in b.processes.items():
            process_name = "[%d] %s" % (
                node_id,
                ",".join([p.name for p in processes]),
            )
            node_id += 1
            nodes.append([process_name, b.name, 0])
            groups = {}
            for v in vmos:
                group_name = None
                for gs in group_specs:
                    if gs[1].match(v.name):
                        if gs[0] in groups:
                            group_name = groups[gs[0]]
                        else:
                            group_name = "[%d] %s" % (node_id, gs[0])
                            node_id += 1
                            groups[gs[0]] = group_name
                            nodes.append([group_name, process_name, 0])
                        break
                vmo_name = "%s<%d>" % (v.name, v.koid)
                nodes.append(
                    [
                        vmo_name,
                        process_name if group_name is None else group_name,
                        v.committed_bytes,
                    ]
                )
    template = """\
<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      google.charts.load('current', {'packages':['treemap']});
      google.charts.setOnLoadCallback(drawChart);

      function drawChart() {
        var data = google.visualization.arrayToDataTable([
          ['Process','Parent','Size (MB)'],
          ['Snapshot',null,0],
            %s
        ]);

        tree = new google.visualization.TreeMap(document.getElementById('chart_div'));

        tree.draw(data, {
          headerHeight: 15,
          fontColor: 'black',
          generateTooltip: showTooltip,
          maxDepth: 2,
          enableHighlight: true,
          minHighlightColor: '#8c6bb1',
          midHighlightColor: '#9ebcda',
          maxHighlightColor: '#edf8fb',
          minColor: '#009688',
          midColor: '#f7f7f7',
          maxColor: '#ee8100'
        });

        function showTooltip(row, size, value) {
          return '<div style="background:#fd9; padding:10px; border-style:solid">' + data.getValue(row, 0) + ' ' + size.toFixed(2) + 'MB</div>';
        }

      }
    </script>
  </head>
  <body>
    <div id="chart_div" style="width: 100%%; height: 100%%;"></div>
  </body>
</html>
"""
    node_strings = "\n".join(
        [
            "['%s','%s',%.2g]," % (n[0], n[1], round(n[2] / (1024.0 * 1024), 2))
            for n in nodes
        ]
    )
    print(template % node_strings)


def main(args):
    snapshot = (
        Snapshot.FromJSONFile(sys.stdin)
        if args.snapshot is None
        else Snapshot.FromJSONFilename(args.snapshot)
    )
    digest = Digest.FromJSONFilename(snapshot, args.digest)

    buckets = sorted(digest.buckets.values(), key=lambda b: b.name)
    if args.output == "csv":
        for bucket in buckets:
            print("%s, %d" % (bucket.name, bucket.size))
    elif args.output == "html":
        output_html(buckets)
    else:
        total = 0
        for bucket in buckets:
            if bucket.size == 0:
                continue
            print("%s: %s" % (bucket.name, fmt_size(bucket.size)))
            total += bucket.size
            if (
                bucket.name != "Undigested"
                and bucket.processes
                and args.verbose
            ):
                entries = []
                for processes, vmos in bucket.processes.items():
                    size = sum([v.committed_bytes for v in vmos])
                    assert size
                    assert len(processes) == 1
                    entries.append((processes[0].name, size))
                # Reverse sort by size.
                entries.sort(key=lambda t: t[1], reverse=True)
                for name, size in entries:
                    print("\t%s: %s" % (name, fmt_size(size)))
        print("\nTotal: %s" % (fmt_size(total)))

        undigested = digest.buckets["Undigested"]
        if undigested.processes:
            print("\nUndigested:")
            entries = []
            for processes, vmos in undigested.processes.items():
                size = sum([v.committed_bytes for v in vmos])
                assert size
                entries.append((processes, size, vmos))

            # Sort by largest sharing pool, then size
            def cmp(entry_a, entry_b):
                if len(entry_b[0]) - len(entry_a[0]):
                    return len(entry_b[0]) - len(entry_a[0])
                return entry_b[1] - entry_a[1]

            entries.sort(key=functools.cmp_to_key(cmp))
            for processes, size, vmos in entries:
                names = [p.full_name for p in processes]
                print("\t%s: %s" % (" ,".join(names), fmt_size(size)))
                for process in processes:
                    if args.verbose:
                        # Group by VMO name, store count and total.
                        print("\t\t%s VMO Summaries:" % process.full_name)
                        groups = {}
                        for v in vmos:
                            cnt, ttl = groups.get(v.name, (0, 0))
                            groups[v.name] = (cnt + 1, ttl + v.committed_bytes)

                        for name, (count, total) in sorted(
                            groups.items(),
                            key=lambda kv: kv[1][1],
                            reverse=True,
                        ):
                            print(
                                "\t\t\t%s (%d): %s"
                                % (name, count, fmt_size(total))
                            )
                    elif args.extra_verbose:
                        # Print "em all
                        print("\t\t%s VMOs:" % process.full_name)
                        for v in sorted(vmos, key=lambda v: v.name):
                            print(
                                "\t\t\t%s[%d]: %s"
                                % (v.name, v.koid, fmt_size(v.committed_bytes))
                            )


def fmt_size(num, suffix="B"):
    for unit in ["", "Ki", "Mi"]:
        if abs(num) < 1024.0:
            return "%.4g%s%s" % (num, unit, suffix)
        num /= 1024.0
    return "%.4g%s%s" % (num, "Gi", suffix)


def get_arg_parser():
    parser = argparse.ArgumentParser(description="Convert snapshot to digest.")
    parser.add_argument("-s", "--snapshot")
    parser.add_argument("-d", "--digest")
    parser.add_argument(
        "-o", "--output", default="human", choices=["csv", "human", "html"]
    )
    parser.add_argument(
        "-v", "--verbose", action=argparse.BooleanOptionalAction, default=False
    )
    parser.add_argument(
        "-vv",
        "--extra_verbose",
        action=argparse.BooleanOptionalAction,
        default=False,
    )
    return parser


if __name__ == "__main__":
    main(get_arg_parser().parse_args())
