// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// This tool creates interactive navigatable binary size reports from
// JSON file generated by the AOT compiler's --print-instructions-sizes-to
// flag.
//
// It used the same visualization framework as Chromium's binary_size tool
// located in runtime/third_party/binary_size.

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math' show max;

import 'package:path/path.dart' as p;

void main(List<String> args) async {
  if (args.length != 2) {
    print(r"""
Usage: run_binary_size_analysis.dart <symbol-sizes.json> <output-directory>

This tool is used to process snapshot size reports produced by
--print-instructions-sizes-to=symbol-sizes.json.

It will create an interactive web-page in the output-directory which can be
viewed in a browser:

$ google-chrome <output-directory>/index.html
""");
    exit(-1);
  }

  final input = new File(args[0]);
  final outputDir = new Directory(args[1]);

  // Load symbols data produced by the AOT compiler and convert it to
  // a tree.
  final symbols = await input
      .openRead()
      .cast<List<int>>()
      .transform(utf8.decoder)
      .transform(json.decoder)
      .first;

  final root = {'n': '', 'children': {}, 'k': kindPath, 'maxDepth': 0};
  for (var symbol in symbols) {
    final name = symbol['n'];
    final size = symbol['s'];

    if (symbol.containsKey('c')) {
      final libraryUri = symbol['l'];
      final className = symbol['c'];
      addSymbol(root, '${libraryUri}/${className}', name, size);
    } else {
      addSymbol(root, '@stubs', name, size);
    }
  }
  final tree = flatten(root);

  // Create output directory and copy all auxiliary files from binary_size tool.
  await outputDir.create(recursive: true);

  final scriptLocation = p.dirname(Platform.script.toFilePath());
  final sdkRoot = p.join(scriptLocation, '..', '..', '..');
  final d3SrcDir = p.join(sdkRoot, 'runtime', 'third_party', 'd3', 'src');
  final templateDir = p.join(
      sdkRoot, 'runtime', 'third_party', 'binary_size', 'src', 'template');

  final d3OutDir = p.join(outputDir.path, 'd3');
  await new Directory(d3OutDir).create(recursive: true);

  for (var file in ['LICENSE', 'd3.js']) {
    await copyFile(d3SrcDir, file, d3OutDir);
  }
  for (var file in ['index.html', 'D3SymbolTreeMap.js']) {
    await copyFile(templateDir, file, outputDir.path);
  }

  // Serialize symbol size tree as JSON.
  final dataJsPath = p.join(outputDir.path, 'data.js');
  final sink = new File(dataJsPath).openWrite();
  sink.write('var tree_data=');
  await sink.addStream(new Stream<Object>.fromIterable([tree])
      .transform(json.encoder.fuse(utf8.encoder)));
  await sink.close();

  // Done.
  print('Generated ${p.toUri(p.absolute(outputDir.path, 'index.html'))}');
}

const kindSymbol = 's';
const kindPath = 'p';
const kindBucket = 'b';
const symbolTypeGlobalText = 'T';

/// Create a child with the given name within the given node or return
/// an existing child.
Map<String, dynamic> addChild(
    Map<String, dynamic> node, String kind, String name) {
  return node['children'].putIfAbsent(name, () {
    final n = <String, dynamic>{'n': name, 'k': kind};
    if (kind != kindSymbol) {
      n['children'] = {};
    }
    return n;
  });
}

/// Add the given symbol to the tree.
void addSymbol(Map<String, dynamic> root, String path, String name, int size) {
  var node = root;
  var depth = 0;
  for (var part in path.split('/')) {
    node = addChild(node, kindPath, part);
    depth++;
  }
  node['lastPathElement'] = true;
  node = addChild(node, kindBucket, symbolTypeGlobalText);
  node['t'] = symbolTypeGlobalText;
  node = addChild(node, kindSymbol, name);
  node['t'] = symbolTypeGlobalText;
  node['value'] = size;
  depth += 2;
  root['maxDepth'] = max<int>(root['maxDepth'], depth);
}

/// Convert all children entries from maps to lists.
Map<String, dynamic> flatten(Map<String, dynamic> node) {
  dynamic children = node['children'];
  if (children != null) {
    children = children.values.map((dynamic v) => flatten(v)).toList();
    node['children'] = children;
    if (children.length == 1 && children.first['k'] == 'p') {
      final singleChild = children.first;
      singleChild['n'] = '${node['n']}/${singleChild['n']}';
      return singleChild;
    }
  }
  return node;
}

/// Copy file with the given name from [fromDir] to [toDir].
Future<void> copyFile(String fromDir, String name, String toDir) async {
  await new File(p.join(fromDir, name)).copy(p.join(toDir, name));
}
