// 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.

import "package:expect/expect.dart";
import "package:dart2js_info/src/graph.dart";

class _NodeInfo {
  int type;
  int name;
  int id;
  int selfSize;
  int edgeCount;
  _NodeInfo(
    this.type,
    this.name,
    this.id,
    this.selfSize,
    this.edgeCount,
  );
}

const List<String> _kRequiredNodeFields = [
  "type",
  "name",
  "id",
  "self_size",
  "edge_count",
];

class _EdgeInfo {
  int type;
  int nameOrIndex;
  int nodeOffset;
  _EdgeInfo(
    this.type,
    this.nameOrIndex,
    this.nodeOffset,
  );
}

const List<String> _kRequiredEdgeFields = [
  "type",
  "name_or_index",
  "to_node",
];

class NodeInfo {
  final String type;
  final String name;
  final int id;
  final int selfSize;
  NodeInfo(
    this.type,
    this.name,
    this.id,
    this.selfSize,
  );
}

class EdgeInfo {
  final int target;
  final String type;

  // Either a string for property names or an int for array/context elements.
  final dynamic nameOrIndex;

  EdgeInfo(this.target, this.type, this.nameOrIndex);
}

class V8SnapshotProfile extends Graph<int> {
  // Indexed by node offset.
  final Map<int, _NodeInfo> _nodes = {};

  // Indexed by start node offset.
  final Map<int, List<_EdgeInfo>> _toEdges = {};
  final Map<int, List<_EdgeInfo>> _fromEdges = {};

  List<String> _nodeFields = [];
  List<String> _edgeFields = [];

  List<String> _nodeTypes = [];
  List<String> _edgeTypes = [];

  List<String> _strings = [];

  // Only used to ensure IDs are unique.
  Set<int> _ids = Set<int>();

  V8SnapshotProfile.fromJson(Map top) {
    final Map snapshot = top["snapshot"];
    _parseMetadata(snapshot["meta"]);

    _parseStrings(top["strings"]);
    Expect.equals(snapshot["node_count"], _parseNodes(top["nodes"]));
    Expect.equals(snapshot["edge_count"], _parseEdges(top["edges"]));

    _verifyRoot();

    _calculateFromEdges();
  }

  void _verifyRoot() {
    // HeapSnapshotWorker.HeapSnapshot.calculateDistances (from HeapSnapshot.js)
    // assumes that the root does not have more than one edge to any other node
    // (most likely an oversight).
    final Set<int> roots = <int>{};
    for (final edge in _toEdges[root]) {
      final int to = edge.nodeOffset;
      Expect.isTrue(!roots.contains(to));
      roots.add(to);
    }

    // Check that all nodes are reachable from the root (offset 0).
    final Set<int> enqueued = {root};
    final dfs = <int>[root];
    while (!dfs.isEmpty) {
      final next = dfs.removeLast();
      for (final edge in _toEdges[next]) {
        if (!enqueued.contains(edge.nodeOffset)) {
          enqueued.add(edge.nodeOffset);
          dfs.add(edge.nodeOffset);
        }
      }
    }
    Expect.equals(enqueued.length, nodeCount);
  }

  void _parseMetadata(Map meta) {
    final List nodeFields = meta["node_fields"];
    nodeFields.forEach(_nodeFields.add);
    Expect.isTrue(_kRequiredNodeFields.every(_nodeFields.contains));

    final List edgeFields = meta["edge_fields"];
    edgeFields.forEach(_edgeFields.add);
    Expect.isTrue(_kRequiredEdgeFields.every(_edgeFields.contains));

    // First entry of "node_types" is an array with the actual node types. IDK
    // what the other entries are for.
    List nodeTypes = meta["node_types"];
    nodeTypes = nodeTypes[0];
    nodeTypes.forEach(_nodeTypes.add);

    // Same for edges.
    List edgeTypes = meta["edge_types"];
    edgeTypes = edgeTypes[0];
    edgeTypes.forEach(_edgeTypes.add);
  }

  int _parseNodes(List nodes) {
    final int typeIndex = _nodeFields.indexOf("type");
    final int nameIndex = _nodeFields.indexOf("name");
    final int idIndex = _nodeFields.indexOf("id");
    final int selfSizeIndex = _nodeFields.indexOf("self_size");
    final int edgeCountIndex = _nodeFields.indexOf("edge_count");

    int offset = 0;
    for (; offset < nodes.length; offset += _nodeFields.length) {
      final int type = nodes[offset + typeIndex];
      Expect.isTrue(0 <= type && type < _nodeTypes.length);

      final int name = nodes[offset + nameIndex];
      Expect.isTrue(0 <= name && name < _strings.length);

      final int id = nodes[offset + idIndex];
      Expect.isTrue(id >= 0);
      Expect.isFalse(_ids.contains(id));
      _ids.add(id);

      final int selfSize = nodes[offset + selfSizeIndex];
      Expect.isTrue(selfSize >= 0);

      final int edgeCount = nodes[offset + edgeCountIndex];
      Expect.isTrue(edgeCount >= 0);

      _nodes[offset] = _NodeInfo(type, name, id, selfSize, edgeCount);
    }

    Expect.equals(offset, nodes.length);
    return offset ~/ _nodeFields.length;
  }

  int _parseEdges(List edges) {
    final int typeIndex = _edgeFields.indexOf("type");
    final int nameOrIndexIndex = _edgeFields.indexOf("name_or_index");
    final int toNodeIndex = _edgeFields.indexOf("to_node");

    int edgeOffset = 0;
    for (int nodeOffset = 0;
        nodeOffset < _nodes.length * _nodeFields.length;
        nodeOffset += _nodeFields.length) {
      final int edgeCount = _nodes[nodeOffset].edgeCount;
      final List<_EdgeInfo> nodeEdges = List<_EdgeInfo>(edgeCount);
      for (int i = 0; i < edgeCount; ++i, edgeOffset += _edgeFields.length) {
        final int type = edges[edgeOffset + typeIndex];
        Expect.isTrue(0 <= type && type < _edgeTypes.length);

        final int nameOrIndex = edges[edgeOffset + nameOrIndexIndex];
        if (_edgeTypes[type] == "property") {
          Expect.isTrue(0 <= nameOrIndex && nameOrIndex < _strings.length);
        } else if (_edgeTypes[type] == "element" ||
            _edgeTypes[type] == "context") {
          Expect.isTrue(nameOrIndex >= 0);
        }

        final int toNode = edges[edgeOffset + toNodeIndex];
        checkNode(toNode);
        nodeEdges[i] = _EdgeInfo(type, nameOrIndex, toNode);
      }
      _toEdges[nodeOffset] = nodeEdges;
    }

    Expect.equals(edgeOffset, edges.length);
    return edgeOffset ~/ _edgeFields.length;
  }

  void checkNode(int offset) {
    Expect.isTrue(offset >= 0 &&
        offset % _nodeFields.length == 0 &&
        offset ~/ _nodeFields.length < _nodes.length);
  }

  void _calculateFromEdges() {
    for (final MapEntry<int, List<_EdgeInfo>> entry in _toEdges.entries) {
      final int fromNode = entry.key;
      for (final _EdgeInfo edge in entry.value) {
        final List<_EdgeInfo> backEdges =
            _fromEdges.putIfAbsent(edge.nodeOffset, () => <_EdgeInfo>[]);
        backEdges.add(_EdgeInfo(edge.type, edge.nameOrIndex, fromNode));
      }
    }
  }

  void _parseStrings(List strings) => strings.forEach(_strings.add);

  int get accountedBytes {
    int sum = 0;
    for (final _NodeInfo info in _nodes.values) {
      sum += info.selfSize;
    }
    return sum;
  }

  int get unknownCount {
    final int unknownType = _nodeTypes.indexOf("Unknown");
    Expect.isTrue(unknownType >= 0);

    int count = 0;
    for (final MapEntry<int, _NodeInfo> entry in _nodes.entries) {
      if (entry.value.type == unknownType) {
        ++count;
      }
    }
    return count;
  }

  bool get isEmpty => _nodes.isEmpty;
  int get nodeCount => _nodes.length;

  Iterable<int> get nodes => _nodes.keys;

  Iterable<int> targetsOf(int source) {
    return _toEdges[source].map((_EdgeInfo i) => i.nodeOffset);
  }

  Iterable<int> sourcesOf(int source) {
    return _fromEdges[source].map((_EdgeInfo i) => i.nodeOffset);
  }

  int get root => 0;

  NodeInfo operator [](int node) {
    _NodeInfo info = _nodes[node];
    final type = info.type != null ? _nodeTypes[info.type] : null;
    final name = info.name != null ? _strings[info.name] : null;
    return NodeInfo(type, name, info.id, info.selfSize);
  }

  Iterable<EdgeInfo> targets(int node) sync* {
    for (final _EdgeInfo info in _toEdges[node]) {
      final String type = _edgeTypes[info.type];
      yield EdgeInfo(info.nodeOffset, type,
          type == "property" ? _strings[info.nameOrIndex] : info.nameOrIndex);
    }
  }
}
