// Copyright (c) 2017, 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.

import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/diff.dart';
import 'package:dart2js_info/src/io.dart';
import 'package:dart2js_info/src/util.dart';

/// A command-line tool that computes the diff between two info files.
main(List<String> args) async {
  if (args.length < 2 || args.length > 3) {
    print('usage: dart2js_info_diff old.info.json new.info.json [--summary]');
    return;
  }

  var oldInfo = await infoFromFile(args[0]);
  var newInfo = await infoFromFile(args[1]);
  var summary = false;
  if (args.length == 3) {
    if (args[2] == "--summary") {
      summary = true;
    } else {
      print('Unrecognized argument: ${args[2]}');
      return;
    }
  }

  var diffs = diff(oldInfo, newInfo);

  // Categorize the diffs
  var adds = <AddDiff>[];
  var removals = <RemoveDiff>[];
  var sizeChanges = <SizeDiff>[];
  var becameDeferred = <DeferredStatusDiff>[];
  var becameUndeferred = <DeferredStatusDiff>[];

  for (var diff in diffs) {
    switch (diff.kind) {
      case DiffKind.add:
        adds.add(diff as AddDiff);
        break;
      case DiffKind.remove:
        removals.add(diff as RemoveDiff);
        break;
      case DiffKind.size:
        sizeChanges.add(diff as SizeDiff);
        break;
      case DiffKind.deferred:
        var deferredDiff = diff as DeferredStatusDiff;
        if (deferredDiff.wasDeferredBefore) {
          becameUndeferred.add(deferredDiff);
        } else {
          becameDeferred.add(deferredDiff);
        }
        break;
    }
  }

  // Sort the changes by the size of the element that changed.
  for (var diffs in [adds, removals, becameDeferred, becameUndeferred]) {
    diffs.sort((a, b) => b.info.size - a.info.size);
  }

  // Sort changes in size by size difference.
  sizeChanges.sort((a, b) => b.sizeDifference - a.sizeDifference);

  var totalSizes = <List<Diff>, int>{};
  for (var diffs in [adds, removals, becameDeferred, becameUndeferred]) {
    var totalSize = 0;
    for (var diff in diffs) {
      // Only count diffs from leaf elements so we don't double count
      // them when we account for class size diff or library size diff.
      if (diff.info.kind == InfoKind.field ||
          diff.info.kind == InfoKind.function ||
          diff.info.kind == InfoKind.closure ||
          diff.info.kind == InfoKind.typedef) {
        totalSize += diff.info.size;
      }
    }
    totalSizes[diffs] = totalSize;
  }
  var totalSizeChange = 0;
  for (var sizeChange in sizeChanges) {
    // Only count diffs from leaf elements so we don't double count
    // them when we account for class size diff or library size diff.
    if (sizeChange.info.kind == InfoKind.field ||
        sizeChange.info.kind == InfoKind.function ||
        sizeChange.info.kind == InfoKind.closure ||
        sizeChange.info.kind == InfoKind.typedef) {
      totalSizeChange += sizeChange.sizeDifference;
    }
  }
  totalSizes[sizeChanges] = totalSizeChange;

  reportSummary(oldInfo, newInfo, adds, removals, sizeChanges, becameDeferred,
      becameUndeferred, totalSizes);
  if (!summary) {
    print('');
    reportFull(oldInfo, newInfo, adds, removals, sizeChanges, becameDeferred,
        becameUndeferred, totalSizes);
  }
}

void reportSummary(
    AllInfo oldInfo,
    AllInfo newInfo,
    List<AddDiff> adds,
    List<RemoveDiff> removals,
    List<SizeDiff> sizeChanges,
    List<DeferredStatusDiff> becameDeferred,
    List<DeferredStatusDiff> becameUndeferred,
    Map<List<Diff>, int> totalSizes) {
  var overallSizeDiff = newInfo.program.size - oldInfo.program.size;
  print('total_size_difference $overallSizeDiff');

  print('total_added ${totalSizes[adds]}');
  print('total_removed ${totalSizes[removals]}');
  print('total_size_changed ${totalSizes[sizeChanges]}');
  print('total_became_deferred ${totalSizes[becameDeferred]}');
  print('total_no_longer_deferred ${totalSizes[becameUndeferred]}');
}

void reportFull(
    AllInfo oldInfo,
    AllInfo newInfo,
    List<AddDiff> adds,
    List<RemoveDiff> removals,
    List<SizeDiff> sizeChanges,
    List<DeferredStatusDiff> becameDeferred,
    List<DeferredStatusDiff> becameUndeferred,
    Map<List<Diff>, int> totalSizes) {
  // TODO(het): Improve this output. Siggi has good suggestions in
  // https://github.com/dart-lang/dart2js_info/pull/19

  _section('ADDED', size: totalSizes[adds]);
  for (var add in adds) {
    print('${longName(add.info, useLibraryUri: true)}: ${add.info.size} bytes');
  }
  print('');

  _section('REMOVED', size: totalSizes[removals]);
  for (var removal in removals) {
    print('${longName(removal.info, useLibraryUri: true)}: '
        '${removal.info.size} bytes');
  }
  print('');

  _section('CHANGED SIZE', size: totalSizes[sizeChanges]);
  for (var sizeChange in sizeChanges) {
    print('${longName(sizeChange.info, useLibraryUri: true)}: '
        '${sizeChange.sizeDifference} bytes');
  }
  print('');

  _section('BECAME DEFERRED', size: totalSizes[becameDeferred]);
  for (var diff in becameDeferred) {
    print('${longName(diff.info, useLibraryUri: true)}: '
        '${diff.info.size} bytes');
  }
  print('');

  _section('NO LONGER DEFERRED', size: totalSizes[becameUndeferred]);
  for (var diff in becameUndeferred) {
    print('${longName(diff.info, useLibraryUri: true)}: '
        '${diff.info.size} bytes');
  }
}

void _section(String title, {int size}) {
  print('$title ($size bytes)');
  print('=' * 72);
}
