#!/usr/bin/env dart
// 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.

// @dart = 2.9

import 'dart:io';

import 'package:kernel/kernel.dart';
import 'package:kernel/binary/ast_from_binary.dart';
import 'package:kernel/src/tool/command_line_util.dart';

void usage() {
  print("Gives an overview of which parts of the dill file");
  print("contributes how many bytes.");
  print("");
  print("Usage: dart <script> dillFile.dill");
  print("The given argument should be an existing file");
  print("that is valid to load as a dill file.");
  exit(1);
}

main(args) {
  CommandLineHelper.requireExactlyOneArgument(args, usage,
      requireFileExists: true);
  List<int> bytes = new File(args[0]).readAsBytesSync();
  try {
    Component p = new Component();
    new WrappedBinaryBuilder(bytes)
      ..readComponent(p)
      ..report();
  } catch (e) {
    print("Argument given isn't a dill file that can be loaded.");
    usage();
  }
}

class WrappedBinaryBuilder extends BinaryBuilder {
  WrappedBinaryBuilder(var _bytes) : super(_bytes, disableLazyReading: true);
  int offsetsSize = 0;
  int stringTableSize = 0;
  int linkTableSize = 0;
  int uriToSourceSize = 0;
  int constantTableSize = 0;
  Map<Uri, int> librarySizes = {};

  int readOffset() {
    offsetsSize -= byteOffset;
    int result = super.readOffset();
    offsetsSize += byteOffset;
    return result;
  }

  void readStringTable(List<String> table) {
    stringTableSize -= byteOffset;
    super.readStringTable(table);
    stringTableSize += byteOffset;
  }

  void readLinkTable(CanonicalName linkRoot) {
    linkTableSize -= byteOffset;
    super.readLinkTable(linkRoot);
    linkTableSize += byteOffset;
  }

  Map<Uri, Source> readUriToSource(bool readCoverage) {
    uriToSourceSize -= byteOffset;
    var result = super.readUriToSource(readCoverage);
    uriToSourceSize += byteOffset;
    return result;
  }

  void readConstantTable() {
    constantTableSize -= byteOffset;
    super.readConstantTable();
    constantTableSize += byteOffset;
  }

  Library readLibrary(Component component, int endOffset) {
    int size = -byteOffset;
    var result = super.readLibrary(component, endOffset);
    size += byteOffset;
    librarySizes[result.importUri] = size;
    return result;
  }

  String _bytesToReadable(int size) {
    const List<String> what = const ["B", "KB", "MB", "GB", "TB"];
    int idx = 0;
    double dSize = size + 0.0;
    while ((idx + 1) < what.length && dSize >= 512) {
      ++idx;
      dSize /= 1024;
    }
    return "${dSize.toStringAsFixed(1)} ${what[idx]} ($size B)";
  }

  void report() {
    print("Offsets: ${_bytesToReadable(offsetsSize)}");
    print("String table: ${_bytesToReadable(stringTableSize)}");
    print("Link table: ${_bytesToReadable(linkTableSize)}");
    print("URI to source table: ${_bytesToReadable(uriToSourceSize)}");
    print("Constant table: ${_bytesToReadable(constantTableSize)}");
    print("");
    for (Uri uri in librarySizes.keys) {
      print("Library '$uri': ${_bytesToReadable(librarySizes[uri])}.");
    }
  }
}
