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

/// Classes for representing information about the program structure.
library vm_snapshot_analysis.program_info;

import 'package:vm_snapshot_analysis/v8_profile.dart';

/// Represents information about compiled program.
class ProgramInfo {
  static const int rootId = 0;
  static const int stubsId = 1;
  static const int unknownId = 2;

  final ProgramInfoNode root;
  final ProgramInfoNode stubs;
  final ProgramInfoNode unknown;
  int _nextId = 3;

  /// V8 snapshot profile if this [ProgramInfo] object was created from an
  /// output of `--write-v8-snapshot-profile-to=...` flag.
  SnapshotInfo? snapshotInfo;

  ProgramInfo._(this.root, this.stubs, this.unknown);

  factory ProgramInfo() {
    final ProgramInfoNode root = ProgramInfoNode._(
        id: rootId, name: '@shared', type: NodeType.libraryNode, parent: null);

    final ProgramInfoNode stubs = ProgramInfoNode._(
        id: stubsId, name: '@stubs', type: NodeType.libraryNode, parent: root);
    root.children[stubs.name] = stubs;

    final ProgramInfoNode unknown = ProgramInfoNode._(
        id: unknownId,
        name: '@unknown',
        type: NodeType.libraryNode,
        parent: root);
    root.children[unknown.name] = unknown;

    return ProgramInfo._(root, stubs, unknown);
  }

  ProgramInfoNode makeNode(
      {required String name,
      required ProgramInfoNode parent,
      required NodeType type}) {
    return parent.children.putIfAbsent(
        name,
        () => ProgramInfoNode._(
            id: _nextId++, name: name, parent: parent, type: type));
  }

  /// Recursively visit all function nodes, which have [FunctionInfo.info]
  /// populated.
  void visit(
      void Function(String? pkg, String lib, String? cls, String? fun,
              ProgramInfoNode n)
          callback) {
    final context = List<String?>.filled(NodeType.values.length, null);

    void recurse(ProgramInfoNode node) {
      final prevContext = context[node._type];
      if (prevContext != null && node._type == NodeType.functionNode.index) {
        context[node._type] = '${prevContext}.${node.name}';
      } else {
        context[node._type] = node.name;
      }

      final pkg = context[NodeType.packageNode.index];
      final lib = context[NodeType.libraryNode.index];
      final cls = context[NodeType.classNode.index];
      final mem = context[NodeType.functionNode.index];
      callback(pkg, lib!, cls, mem, node);

      for (var child in node.children.values) {
        recurse(child);
      }

      context[node._type] = prevContext;
    }

    recurse(root);
  }

  /// Total size of all the nodes in the program.
  int get totalSize => root.totalSize;

  /// Convert this program info to a JSON map using [infoToJson] to convert
  /// data attached to nodes into its JSON representation.
  Map<String, dynamic> toJson() => root.toJson();

  /// Lookup a node in the program given a path to it.
  ProgramInfoNode? lookup(List<String> path) {
    var n = root;
    for (var p in path) {
      final next = n.children[p];
      if (next == null) {
        return null;
      }
      n = next;
    }
    return n;
  }
}

enum NodeType {
  packageNode,
  libraryNode,
  classNode,
  functionNode,
  other,
}

String _typeToJson(NodeType type) => const {
      NodeType.packageNode: 'package',
      NodeType.libraryNode: 'library',
      NodeType.classNode: 'class',
      NodeType.functionNode: 'function',
      NodeType.other: 'other',
    }[type]!;

class ProgramInfoNode {
  final int id;
  final String name;
  final ProgramInfoNode? parent;
  final Map<String, ProgramInfoNode> children = {};
  final int _type;

  /// Number of bytes in the snapshot which can be attributed to this node.
  ///
  /// Note that this is neither a shallow size of the object that represents
  /// this node in the AOT snapshot, nor a cumulative size of its children.
  /// Instead this size is similar to _retained size_ used by heap profiling
  /// tools. Snapshot nodes corresponding to the info nodes are viewed as
  /// a dominator tree and all nodes in the snapshot are partitioned based
  /// on which node of this tree dominates them.
  ///
  /// Consider for example the following Dart code:
  ///
  ///     ```dart
  ///     class C {
  ///       void f() { use("something"); }
  ///       void g() { use("something"); }
  ///     }
  ///     ```
  ///
  /// Assuming that both `C.f` and `C.g` are included into AOT snapshot
  /// and string `"something"` does not occur anywhere else in the program
  /// then the size of `"something"` is going to be attributed to `C`.
  int? size;

  ProgramInfoNode._(
      {required this.id,
      required this.name,
      required this.parent,
      required NodeType type})
      : _type = type.index;

  NodeType get type => NodeType.values[_type];

  Map<String, dynamic> toJson() => {
        if (size != null) '#size': size,
        if (_type != NodeType.other.index) '#type': _typeToJson(type),
        if (children.isNotEmpty)
          for (var clo in children.entries) clo.key: clo.value.toJson()
      };

  /// Returns the name of this node prefixed by the [qualifiedName] of its
  /// [parent].
  String get qualifiedName {
    var prefix = '';
    // Do not include root name or package name (library uri already contains
    // package name).
    final p = parent;
    if (p != null && p.parent != null && p.type != NodeType.packageNode) {
      prefix = p.qualifiedName;
      if (p.type != NodeType.libraryNode) {
        prefix += '.';
      } else {
        prefix += '::';
      }
    }
    return '$prefix$name';
  }

  @override
  String toString() {
    return '${_typeToJson(type)} ${qualifiedName}';
  }

  /// Returns path to this node such that [ProgramInfo.lookup] would return
  /// this node given its [path].
  List<String> get path {
    final result = <String>[];
    var n = this;
    while (n.parent != null) {
      result.add(n.name);
      n = n.parent!;
    }
    return result.reversed.toList();
  }

  /// Cumulative size of this node and all of its children.
  int get totalSize {
    return (size ?? 0) +
        children.values.fold<int>(0, (s, n) => s + n.totalSize);
  }
}

/// Computes the size difference between two [ProgramInfo].
ProgramInfo computeDiff(ProgramInfo oldInfo, ProgramInfo newInfo) {
  final programDiff = ProgramInfo();

  var path = <Object>[];
  void recurse(ProgramInfoNode? oldNode, ProgramInfoNode? newNode) {
    if (oldNode?.size != newNode?.size) {
      var diffNode = programDiff.root;
      for (var i = 0; i < path.length; i += 2) {
        final name = path[i] as String;
        final type = path[i + 1] as NodeType;
        diffNode =
            programDiff.makeNode(name: name, parent: diffNode, type: type);
      }
      diffNode.size =
          (diffNode.size ?? 0) + (newNode?.size ?? 0) - (oldNode?.size ?? 0);
    }

    for (var key in _allKeys(newNode?.children, oldNode?.children)) {
      final newChildNode = newNode != null ? newNode.children[key] : null;
      final oldChildNode = oldNode != null ? oldNode.children[key] : null;
      path.add(key);
      path.add((oldChildNode?.type ?? newChildNode?.type)!);
      recurse(oldChildNode, newChildNode);
      path.removeLast();
      path.removeLast();
    }
  }

  recurse(oldInfo.root, newInfo.root);

  return programDiff;
}

Iterable<T> _allKeys<T>(Map<T, dynamic>? a, Map<T, dynamic>? b) {
  return <T>{...?a?.keys, ...?b?.keys};
}

class Histogram {
  /// Rule used to produce this histogram. Specifies how bucket names
  /// are constructed given (library-uri,class-name,function-name) tuples and
  /// how these bucket names can be deconstructed back into human readable form.
  final BucketInfo bucketInfo;

  /// Histogram buckets.
  final Map<String, int> buckets;

  /// Bucket names sorted by the size of the corresponding bucket in descending
  /// order.
  final List<String> bySize;

  final int totalSize;

  int get length => bySize.length;

  Histogram._(this.bucketInfo, this.buckets)
      : bySize = buckets.keys.toList(growable: false)
          ..sort((a, b) => buckets[b]! - buckets[a]!),
        totalSize = buckets.values.fold(0, (sum, size) => sum + size);

  static Histogram fromIterable<T>(
    Iterable<T> entries, {
    required int Function(T) sizeOf,
    required String Function(T) bucketFor,
    required BucketInfo bucketInfo,
  }) {
    final buckets = <String, int>{};

    for (var e in entries) {
      final bucket = bucketFor(e);
      final size = sizeOf(e);
      buckets[bucket] = (buckets[bucket] ?? 0) + size;
    }

    return Histogram._(bucketInfo, buckets);
  }

  /// Rebuckets the histogram given the new bucketing rule.
  Histogram map(String Function(String) bucketFor) {
    return Histogram.fromIterable(buckets.keys,
        sizeOf: (key) => buckets[key]!,
        bucketFor: bucketFor,
        bucketInfo: bucketInfo);
  }
}

/// Construct the histogram of specific [type] given a [ProgramInfo].
///
/// [filter] glob can be provided to skip some of the nodes in the [info]:
/// a string is created which contains library name, class name and function
/// name for the given node and if this string does not match the [filter]
/// glob then this node is ignored.
Histogram computeHistogram(ProgramInfo info, HistogramType type,
    {String? filter}) {
  bool Function(String, String?, String?) matchesFilter;

  if (filter != null) {
    final re = RegExp(filter.replaceAll('*', '.*'), caseSensitive: false);
    matchesFilter =
        (lib, cls, fun) => re.hasMatch("${lib}::${cls ?? ''}.${fun ?? ''}");
  } else {
    matchesFilter = (_, __, ___) => true;
  }

  if (type == HistogramType.byNodeType) {
    final Set<int> filteredNodes = {};
    if (filter != null) {
      info.visit((pkg, lib, cls, fun, node) {
        if (matchesFilter(lib, cls, fun)) {
          filteredNodes.add(node.id);
        }
      });
    }

    final snapshotInfo = info.snapshotInfo!;

    return Histogram.fromIterable<Node>(
        snapshotInfo.snapshot.nodes.where((n) =>
            filter == null ||
            filteredNodes.contains(snapshotInfo.ownerOf(n).id)),
        sizeOf: (n) {
          return n.selfSize;
        },
        bucketFor: (n) => n.type,
        bucketInfo: const BucketInfo(nameComponents: ['Type']));
  } else {
    final buckets = <String, int>{};
    final bucketing = Bucketing._forType[type]!;

    info.visit((pkg, lib, cls, fun, node) {
      final sz = node.size;
      if (sz == null || sz == 0) {
        return;
      }
      if (!matchesFilter(lib, cls, fun)) {
        return;
      }
      final bucket = bucketing.bucketFor(pkg, lib, cls, fun);
      buckets[bucket] = (buckets[bucket] ?? 0) + sz;
    });

    return Histogram._(bucketing, buckets);
  }
}

enum HistogramType {
  bySymbol,
  byClass,
  byLibrary,
  byPackage,
  byNodeType,
}

class BucketInfo {
  /// Specifies which human readable name components can be extracted from
  /// the bucket name.
  final List<String> nameComponents;

  /// Deconstructs bucket name into human readable components (the order matches
  /// one returned by [nameComponents]).
  List<String> namesFromBucket(String bucket) => [bucket];

  const BucketInfo({required this.nameComponents});
}

abstract class Bucketing extends BucketInfo {
  /// Constructs the bucket name from the given library name [lib], class name
  /// [cls] and function name [fun].
  String bucketFor(String? pkg, String lib, String? cls, String? fun);

  const Bucketing({required List<String> nameComponents})
      : super(nameComponents: nameComponents);

  static const _forType = {
    HistogramType.bySymbol: _BucketBySymbol(),
    HistogramType.byClass: _BucketByClass(),
    HistogramType.byLibrary: _BucketByLibrary(),
    HistogramType.byPackage: _BucketByPackage(),
  };
}

/// A combination of characters that is unlikely to occur in the symbol name.
const String _nameSeparator = ';;;';

class _BucketBySymbol extends Bucketing {
  @override
  String bucketFor(String? pkg, String lib, String? cls, String? fun) {
    if (fun == null) {
      return '@other${_nameSeparator}';
    }
    return '$lib${_nameSeparator}${cls ?? ''}${cls != '' && cls != null ? '.' : ''}${fun}';
  }

  @override
  List<String> namesFromBucket(String bucket) => bucket.split(_nameSeparator);

  const _BucketBySymbol() : super(nameComponents: const ['Library', 'Symbol']);
}

class _BucketByClass extends Bucketing {
  @override
  String bucketFor(String? pkg, String lib, String? cls, String? fun) {
    if (cls == null) {
      return '@other${_nameSeparator}';
    }
    return '$lib${_nameSeparator}${cls}';
  }

  @override
  List<String> namesFromBucket(String bucket) => bucket.split(_nameSeparator);

  const _BucketByClass() : super(nameComponents: const ['Library', 'Class']);
}

class _BucketByLibrary extends Bucketing {
  @override
  String bucketFor(String? pkg, String lib, String? cls, String? fun) => '$lib';

  const _BucketByLibrary() : super(nameComponents: const ['Library']);
}

class _BucketByPackage extends Bucketing {
  @override
  String bucketFor(String? pkg, String lib, String? cls, String? fun) =>
      pkg ?? lib;

  const _BucketByPackage() : super(nameComponents: const ['Package']);
}

String packageOf(String lib) {
  if (lib.startsWith('package:')) {
    final separatorPos = lib.indexOf('/');
    return lib.substring(0, separatorPos);
  } else {
    return lib;
  }
}
