// Copyright 2014 The Flutter 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 'package:meta/meta.dart';
import 'package:vm_snapshot_analysis/treemap.dart';

import '../base/file_system.dart';
import '../convert.dart';
import 'logger.dart';
import 'process.dart';
import 'terminal.dart';

/// A class to analyze APK and AOT snapshot and generate a breakdown of the data.
class SizeAnalyzer {
  SizeAnalyzer({
    @required this.fileSystem,
    @required this.logger,
    @required this.processUtils,
    this.appFilenamePattern = 'libapp.so',
  });

  final FileSystem fileSystem;
  final Logger logger;
  final ProcessUtils processUtils;
  final Pattern appFilenamePattern;
  String _appFilename;

  static const String aotSnapshotFileName = 'aot-snapshot.json';

  static const int tableWidth = 80;

  /// Analyzes [apk] and [aotSnapshot] to output a [Map] object that includes
  /// the breakdown of the both files, where the breakdown of [aotSnapshot] is placed
  /// under 'lib/arm64-v8a/$_appFilename'.
  ///
  /// The [aotSnapshot] can be either instruction sizes snapshot or v8 snapshot.
  Future<Map<String, dynamic>> analyzeApkSizeAndAotSnapshot({
    @required File apk,
    @required File aotSnapshot,
  }) async {
    logger.printStatus('▒' * tableWidth);
    _printEntitySize(
      '${apk.basename} (total compressed)',
      byteSize: apk.lengthSync(),
      level: 0,
      showColor: false,
    );
    logger.printStatus('━' * tableWidth);
    final Directory tempApkContent = fileSystem.systemTempDirectory.createTempSync('flutter_tools.');
    // TODO(peterdjlee): Implement a way to unzip the APK for Windows. See issue #62603.
    String unzipOut;
    try {
      // TODO(peterdjlee): Use zipinfo instead of unzip.
      unzipOut = (await processUtils.run(<String>[
        'unzip',
        '-o',
        '-v',
        apk.path,
        '-d',
        tempApkContent.path
      ])).stdout;
    } on Exception catch (e) {
      logger.printError(e.toString());
    } finally {
      // We just want the the stdout printout. We don't need the files.
      tempApkContent.deleteSync(recursive: true);
    }

    final _SymbolNode apkAnalysisRoot = _parseUnzipFile(unzipOut);

    // Convert an AOT snapshot file into a map.
    final Map<String, dynamic> processedAotSnapshotJson = treemapFromJson(
      json.decode(aotSnapshot.readAsStringSync()),
    );
    final _SymbolNode aotSnapshotJsonRoot = _parseAotSnapshot(processedAotSnapshotJson);

    for (final _SymbolNode firstLevelPath in apkAnalysisRoot.children) {
      _printEntitySize(
        firstLevelPath.name,
        byteSize: firstLevelPath.byteSize,
        level: 1,
      );
      // Print the expansion of lib directory to show more info for `appFilename`.
      if (firstLevelPath.name == 'lib') {
        _printLibChildrenPaths(firstLevelPath, '', aotSnapshotJsonRoot);
      }
    }

    logger.printStatus('▒' * tableWidth);

    Map<String, dynamic> apkAnalysisJson = apkAnalysisRoot.toJson();

    apkAnalysisJson['type'] = 'apk';

    // TODO(peterdjlee): Add aot snapshot for all platforms.
    assert(_appFilename != null);
    apkAnalysisJson = _addAotSnapshotDataToApkAnalysis(
      apkAnalysisJson: apkAnalysisJson,
      path: 'lib/arm64-v8a/$_appFilename (Dart AOT)'.split('/'), // Pass in a list of paths by splitting with '/'.
      aotSnapshotJson: processedAotSnapshotJson,
    );

    return apkAnalysisJson;
  }


  // Expression to match 'Size' column to group 1 and 'Name' column to group 2.
  final RegExp _parseUnzipOutput = RegExp(r'^\s*\d+\s+[\w|:]+\s+(\d+)\s+.*  (.+)$');

  // Parse the output of unzip -v which shows the zip's contents' compressed sizes.
  // Example output of unzip -v:
  //  Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
  // --------  ------  ------- ---- ---------- ----- --------  ----
  //    11708  Defl:N     2592  78% 00-00-1980 00:00 07733eef  AndroidManifest.xml
  //     1399  Defl:N     1092  22% 00-00-1980 00:00 f53d952a  META-INF/CERT.RSA
  //    46298  Defl:N    14530  69% 00-00-1980 00:00 17df02b8  META-INF/CERT.SF
  _SymbolNode _parseUnzipFile(String unzipOut) {
    final Map<List<String>, int> pathsToSize = <List<String>, int>{};

    // Parse each path into pathsToSize so that the key is a list of
    // path parts and the value is the size.
    // For example:
    // 'path/to/file' where file = 1500 => pathsToSize[['path', 'to', 'file']] = 1500
    for (final String line in const LineSplitter().convert(unzipOut)) {
      final RegExpMatch match = _parseUnzipOutput.firstMatch(line);
      if (match == null) {
        continue;
      }
      const int sizeGroupIndex = 1;
      const int nameGroupIndex = 2;
      pathsToSize[match.group(nameGroupIndex).split('/')] = int.parse(match.group(sizeGroupIndex));
    }

    final _SymbolNode rootNode = _SymbolNode('Root');

    _SymbolNode currentNode = rootNode;
    for (final List<String> paths in pathsToSize.keys) {
      for (final String path in paths) {
        _SymbolNode childWithPathAsName = currentNode.childByName(path);

        if (childWithPathAsName == null) {
          childWithPathAsName = _SymbolNode(path);
          if (matchesPattern(path, pattern: appFilenamePattern) != null) {
            _appFilename = path;
            childWithPathAsName.name += ' (Dart AOT)';
          } else if (path == 'libflutter.so') {
            childWithPathAsName.name += ' (Flutter Engine)';
          }
          currentNode.addChild(childWithPathAsName);
        }
        childWithPathAsName.addSize(pathsToSize[paths]);
        currentNode = childWithPathAsName;
      }
      currentNode = rootNode;
    }

    return rootNode;
  }

  /// Prints all children paths for the lib/ directory in an APK.
  ///
  /// A brief summary of aot snapshot is printed under 'lib/arm64-v8a/$_appFilename'.
  void _printLibChildrenPaths(
    _SymbolNode currentNode,
    String totalPath,
    _SymbolNode aotSnapshotJsonRoot,
  ) {
    totalPath += currentNode.name;

    assert(_appFilename != null);
    if (currentNode.children.isNotEmpty
      && currentNode.name != '$_appFilename (Dart AOT)') {
      for (final _SymbolNode child in currentNode.children) {
        _printLibChildrenPaths(child, '$totalPath/', aotSnapshotJsonRoot);
      }
    } else {
      // Print total path and size if currentNode does not have any chilren.
      _printEntitySize(totalPath, byteSize: currentNode.byteSize, level: 2);

      // We picked this file because arm64-v8a is likely the most popular
      // architecture. Other architecture sizes should be similar.
      final String libappPath = 'lib/arm64-v8a/$_appFilename';
      // TODO(peterdjlee): Analyze aot size for all platforms.
      if (totalPath.contains(libappPath)) {
        _printAotSnapshotSummary(aotSnapshotJsonRoot);
      }
    }
  }

  /// Go through the AOT gen snapshot size JSON and print out a collapsed summary
  /// for the first package level.
  void _printAotSnapshotSummary(_SymbolNode aotSnapshotRoot, {int maxDirectoriesShown = 10}) {
    _printEntitySize(
      'Dart AOT symbols accounted decompressed size',
      byteSize: aotSnapshotRoot.byteSize,
      level: 3,
    );

    final List<_SymbolNode> sortedSymbols = aotSnapshotRoot.children.toList()
      ..sort((_SymbolNode a, _SymbolNode b) => b.byteSize.compareTo(a.byteSize));
    for (final _SymbolNode node in sortedSymbols.take(maxDirectoriesShown)) {
      _printEntitySize(node.name, byteSize: node.byteSize, level: 4);
    }
  }

  /// Adds breakdown of aot snapshot data as the children of the node at the given path.
  Map<String, dynamic> _addAotSnapshotDataToApkAnalysis({
    @required Map<String, dynamic> apkAnalysisJson,
    @required List<String> path,
    @required Map<String, dynamic> aotSnapshotJson,
  }) {
    Map<String, dynamic> currentLevel = apkAnalysisJson;
    while (path.isNotEmpty) {
      final List<Map<String, dynamic>> children = currentLevel['children'] as List<Map<String, dynamic>>;
      final Map<String, dynamic> childWithPathAsName = children.firstWhere(
        (Map<String, dynamic> child) => child['n'] as String == path.first,
      );
      path.removeAt(0);
      currentLevel = childWithPathAsName;
    }
    currentLevel['children'] = aotSnapshotJson['children'];
    return apkAnalysisJson;
  }

  /// Print an entity's name with its size on the same line.
  void _printEntitySize(
    String entityName, {
    @required int byteSize,
    @required int level,
    bool showColor = true,
  }) {
    final bool emphasis = level <= 1;
    final String formattedSize = _prettyPrintBytes(byteSize);

    TerminalColor color = TerminalColor.green;
    if (formattedSize.endsWith('MB')) {
      color = TerminalColor.cyan;
    } else if (formattedSize.endsWith('KB')) {
      color = TerminalColor.yellow;
    }

    final int spaceInBetween = tableWidth - level * 2 - entityName.length - formattedSize.length;
    logger.printStatus(
      entityName + ' ' * spaceInBetween,
      newline: false,
      emphasis: emphasis,
      indent: level * 2,
    );
    logger.printStatus(formattedSize, color: showColor ? color : null);
  }

  String _prettyPrintBytes(int numBytes) {
    const int kB = 1024;
    const int mB = kB * 1024;
    if (numBytes < kB) {
      return '$numBytes B';
    } else if (numBytes < mB) {
      return '${(numBytes / kB).round()} KB';
    } else {
      return '${(numBytes / mB).round()} MB';
    }
  }

  _SymbolNode _parseAotSnapshot(Map<String, dynamic> aotSnapshotJson) {
    final bool isLeafNode = aotSnapshotJson['children'] == null;
    if (!isLeafNode) {
      return _buildNodeWithChildren(aotSnapshotJson);
    } else {
      // TODO(peterdjlee): Investigate why there are leaf nodes with size of null.
      final int byteSize = aotSnapshotJson['value'] as int;
      if (byteSize == null) {
        return null;
      }
      return _buildNode(aotSnapshotJson, byteSize);
    }
  }

  _SymbolNode _buildNode(
    Map<String, dynamic> aotSnapshotJson,
    int byteSize, {
    List<_SymbolNode> children = const <_SymbolNode>[],
  }) {
    final String name = aotSnapshotJson['n'] as String;
    final Map<String, _SymbolNode> childrenMap = <String, _SymbolNode>{};

    for (final _SymbolNode child in children) {
      childrenMap[child.name] = child;
    }

    return _SymbolNode(
      name,
      byteSize: byteSize,
    )..addAllChildren(children);
  }

  /// Builds a node by recursively building all of its children first
  /// in order to calculate the sum of its children's sizes.
  _SymbolNode _buildNodeWithChildren(Map<String, dynamic> aotSnapshotJson) {
    final List<dynamic> rawChildren = aotSnapshotJson['children'] as List<dynamic>;
    final List<_SymbolNode> symbolNodeChildren = <_SymbolNode>[];
    int totalByteSize = 0;

    // Given a child, build its subtree.
    for (final dynamic child in rawChildren) {
      final _SymbolNode childTreemapNode = _parseAotSnapshot(child as Map<String, dynamic>);
      symbolNodeChildren.add(childTreemapNode);
      totalByteSize += childTreemapNode.byteSize;
    }

    // If none of the children matched the diff tree type
    if (totalByteSize == 0) {
      return null;
    } else {
      return _buildNode(
        aotSnapshotJson,
        totalByteSize,
        children: symbolNodeChildren,
      );
    }
  }
}

/// A node class that represents a single symbol for AOT size snapshots.
class _SymbolNode {
  _SymbolNode(
    this.name, {
    this.byteSize = 0,
  })  : assert(name != null),
        assert(byteSize != null),
        _children = <String, _SymbolNode>{};

  /// The human friendly identifier for this node.
  String name;

  int byteSize;
  void addSize(int sizeToBeAdded) {
    byteSize += sizeToBeAdded;
  }

  _SymbolNode get parent => _parent;
  _SymbolNode _parent;

  Iterable<_SymbolNode> get children => _children.values;
  final Map<String, _SymbolNode> _children;

  _SymbolNode childByName(String name) => _children[name];

  _SymbolNode addChild(_SymbolNode child) {
    assert(child.parent == null);
    assert(!_children.containsKey(child.name),
        'Cannot add duplicate child key ${child.name}');

    child._parent = this;
    _children[child.name] = child;
    return child;
  }

  void addAllChildren(List<_SymbolNode> children) {
    children.forEach(addChild);
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> json = <String, dynamic>{
      'n': name,
      'value': byteSize
    };
    final List<Map<String, dynamic>> childrenAsJson = <Map<String, dynamic>>[];
    for (final _SymbolNode child in children) {
      childrenAsJson.add(child.toJson());
    }
    if (childrenAsJson.isNotEmpty) {
      json['children'] = childrenAsJson;
    }
    return json;
  }
}

/// Matches `pattern` against the entirety of `string`.
@visibleForTesting
Match matchesPattern(String string, {@required Pattern pattern}) {
  final Match match = pattern.matchAsPrefix(string);
  return (match != null && match.end == string.length) ? match : null;
}
