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

import 'package:front_end/src/api_unstable/dart2js.dart'
    show $0, $9, $A, $Z, $a, $z;

/// Returns a list of strings that are short valid identifiers based on the
/// corresponding full strings in [strings].
///
/// [strings] must not contain the empty string.
/// [strings] must have no duplicates.
List<String> abbreviateToIdentifiers(Iterable<String> strings,
    {int minLength = 6}) {
  var nodes = [for (final string in strings) _Node(string)];
  _partition(nodes, minLength, [], 0);
  return [for (final node in nodes) node.assignment];
}

class _Node {
  final String string;
  late String assignment;
  _Node(this.string);
}

/// Walk the prefix tree or TRIE of [nodes], assigning compressed names built
/// from the distinguishing characters along the path.
///
/// - [index] is the position of the first potentially different character,
///   i.e. the current TRIE depth.
/// - [path] contains the prefix of the compressed name at this depth.
/// - Path compression starts after the first [minLength] characters.
void _partition(
    List<_Node> nodes, int minLength, List<String> path, int index) {
  while (true) {
    // Handle trivial partitions.
    if (nodes.length == 0) return;
    if (nodes.length == 1 && path.length >= minLength) {
      String name = path.join();
      assert(name.isNotEmpty);
      nodes.single.assignment = name;
      return;
    }

    // Partition on the code unit at position [index], setting [terminating] if
    // some string ends at this length;
    Map<int, List<_Node>> partition = {};
    _Node? terminating;

    for (final node in nodes) {
      String string = node.string;
      assert(string.length > 0);
      if (index < string.length) {
        int codeUnit = string.codeUnitAt(index);
        (partition[codeUnit] ??= []).add(node);
      } else {
        assert(terminating == null); // i.e. no duplicates.
        terminating = node;
      }
    }

    if (terminating != null) {
      terminating.assignment = path.join();
    }

    if (partition.length == 0) return;

    if (partition.length > 1) {
      var keys = partition.keys.toList();
      var keyEncodings = _discriminators(keys, path.isEmpty);
      for (int key in keys) {
        var children = partition[key]!;
        var discriminator = keyEncodings[key]!;
        _partition(children, minLength, [...path, discriminator], index + 1);
      }
      return;
    }

    assert(partition.length == 1);
    // All the strings have the same code unit at [index]. Use iteration to
    // find next partition point to avoid recursing down the whole string
    // length. The path is compressed by omitting to add fragments to [path]
    // unless we are near the start of the string.

    int codeUnit = partition.keys.single;
    // Add some characters to name to distinguish from terminating strings.
    // Add the first few legal identifier characters of the string regardless.
    if (terminating != null || path.length < minLength) {
      path.add(_isIdentifier(codeUnit, path.isEmpty)
          ? String.fromCharCode(codeUnit)
          : '_');
    }
    nodes = partition.values.single;
    index += 1;
  }
}

Map<int, String> _discriminators(List<int> keys, bool atStart) {
  // Assign each partition a distinguishing short string. If the partition key
  // is a valid identifier character, it can be used, otherwise we could use
  // `'_'` or an escaped code like `'x3b'` or `'u12ef'`. If we use an escape
  // like `'x3b'` then we need to be careful with the partition key `x`, as it
  // might be followed by `3b`. We avoid this problem without lookahead by
  // encoding `x` as an escape (i.e. `'x78'`) if there is another `x`-escape.

  const xCode = 0x78;
  const uCode = 0x75;

  bool hasX = false;
  bool hasU = false;

  int xEscapes = 0;
  int uEscapes = 0;
  for (int key in keys) {
    if (_isIdentifier(key, atStart)) {
      if (key == xCode) hasX = true;
      if (key == uCode) hasU = true;
    } else if (key < 256) {
      xEscapes++;
    } else {
      uEscapes++;
    }
  }

  Map<int, String> encoding = {};
  bool escapeToUnderscore = false;

  if (uEscapes + xEscapes <= 1) {
    escapeToUnderscore = true;
    xEscapes = uEscapes = 0;
  }

  if (uEscapes > 0 && hasU) {
    encoding[uCode] = 'x75';
    xEscapes++;
  }
  if (xEscapes > 0 && hasX) {
    encoding[xCode] = 'x78';
  }

  for (int key in keys) {
    if (encoding.containsKey(key)) continue;
    if (_isIdentifier(key, atStart)) {
      encoding[key] = String.fromCharCode(key);
    } else {
      if (escapeToUnderscore) {
        encoding[key] = '_';
      } else if (key < 256) {
        encoding[key] = 'x' + key.toRadixString(16).padLeft(2, '0');
      } else {
        encoding[key] = 'u' + key.toRadixString(16).padLeft(4, '0');
      }
    }
  }

  return encoding;
}

bool _isIdentifier(int codeUnit, bool atStart) {
  return atStart ? _isAsciiAlpha(codeUnit) : _isAsciiAlphanumeric(codeUnit);
}

bool _isAsciiAlphanumeric(int codeUnit) {
  return $0 <= codeUnit && codeUnit <= $9 || _isAsciiAlpha(codeUnit);
}

bool _isAsciiAlpha(int codeUnit) {
  return $A <= codeUnit && codeUnit <= $Z || $a <= codeUnit && codeUnit <= $z;
}
