#!/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.
"""
This script supports visualizing all histograms found in an inspect snapshot.

To use you need to have a snapshot.zip file either generated by `ffx snapshot` or from a crash
report. This also works by dumping the output of `ffx --machine json inspect` to a file.

Example usage:

```
$ unzip /path/to/snapshot.zip
$ fuchsia-vendored-python snapshot_histograms.py /path/to/unzipped/inspect.json
// open html in browser.
```
"""

import argparse
import json
import sys


def extract_buckets(
    payload: dict[str, object], current_path: list[str] = []
) -> list[tuple[str, str]]:
    result = []
    for key, child in payload.items():
        if type(child) is not dict:
            continue
        if "buckets" in child:
            path = current_path + [key]
            result.append(("/".join(path), child["buckets"]))
            continue
        result.extend(extract_buckets(child, current_path + [key]))
    return result


HTML_DATA = """
<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      google.charts.load('current', {packages: ['corechart', 'table']});
      google.charts.setOnLoadCallback(onLoad);
      const allData = {DATA};
      let showTables = false;

      function drawChart(charts, nodePath, buckets) {
        let data = [['Range', 'Count']];
        for (const bucket of buckets) {
          if (bucket.ceiling === bucket.floor) { continue; }
          data.push([
            { v: bucket.floor, f: `${bucket.floor}-${bucket.ceiling}`},
            bucket.count
          ]);
        }
        let dataTable = google.visualization.arrayToDataTable(data);

        let chartDiv = document.createElement('div');
        chartDiv.classList.add('chart');
        charts.appendChild(chartDiv);

        let tableDiv = document.createElement('div');
        tableDiv.classList.add('table');
        tableDiv.hidden = !showTables;
        charts.appendChild(tableDiv);

        const chart = new google.visualization.ColumnChart(chartDiv);
        chart.draw(dataTable, {
          title: nodePath,
          hAxis: {
            title: 'Ranges',
            logScale: true,
          },
        });

        const table = new google.visualization.Table(tableDiv);
        table.draw(dataTable, {showRowNumber: true, 'max-height': '100px'});
      }

      function render(moniker) {
        if (moniker !== undefined) {
          let charts = document.getElementById('charts');
          charts.innerHTML = '';
          for (const nodePath of Object.keys(allData[moniker])) {
            drawChart(charts, nodePath, allData[moniker][nodePath]);
          }
        }
      }

      function onLoad() {
        const select = document.querySelector('#monikers');
        let selectedMoniker = undefined;
        for (const moniker of Object.keys(allData)) {
          const opt = document.createElement('option');
          opt.innerText = moniker;
          opt.setAttribute('value', moniker);
          select.appendChild(opt);
        }
        select.addEventListener('change', (event) => {
          render(event.target.value);
        });

        const showTablesCheckbox = document.querySelector('#show-tables');
        showTablesCheckbox.addEventListener('change', (event) => {
          showTables = event.target.checked;
                console.log('got change', showTables);
          for (const element of document.getElementsByClassName('table')) {
            console.log(`Changing ${element} to ${!showTables}`);
            element.hidden = !showTables;
          }
        });
      }
    </script>
  </head>
  <body>
    <select id="monikers">
      <option value="" disabled selected>Select moniker</option>
    </select>
    <input type="checkbox" id="show-tables"> Show tables
    <div id="charts"></div>
  </body>
</html>
"""

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Show histograms in a snapshot."
    )
    parser.add_argument(
        "filepath", metavar="FILE", type=str, help="path to inspect.json file"
    )
    args = parser.parse_args(sys.argv[1:])
    results = {}
    with open(args.filepath) as f:
        data = json.load(f)
        for response in data:
            if response["payload"]:
                buckets = extract_buckets(response["payload"])
                if buckets:
                    results[response["moniker"]] = dict(buckets)
    html = HTML_DATA.replace("{DATA}", "{}".format(results))
    print(html)
