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

// @dart = 2.7

import "package:expect/expect.dart";

import 'package:compiler/src/constants/values.dart' show StringConstantValue;
import 'package:compiler/src/js_backend/string_reference.dart'
    show StringReference, StringReferenceResource, StringReferenceFinalizerImpl;

import 'package:compiler/src/js/js.dart' show prettyPrint;
import 'package:js_ast/js_ast.dart' as js;

void test(List<String> strings, String expected, {bool minified: false}) {
  var finalizer =
      StringReferenceFinalizerImpl(minified, shortestSharedLength: 5);

  for (var string in strings) {
    finalizer.addCode(StringReference(StringConstantValue(string)));
  }

  StringReferenceResource resource = StringReferenceResource();
  finalizer.registerStringReferenceResource(resource);
  finalizer.finalize();

  // Wrap the resource in a block, as they would print in actual code.
  Expect.equals(expected.trim(), prettyPrint(js.Block([resource])).trim());
}

extension on List<String> {
  // TODO(42122): Remove when analyzer doesn't think `*` is unused.
  // ignore: unused_element
  List<String> operator *(int count) {
    return List.filled(count, this).expand((list) => list).toList();
  }
}

void main() {
  // No strings yields an empty pool.
  test([], r'''
{
}''');

  // Single occurrence strings are not pooled.
  test(
    ['Yellow', 'Blue', 'Crimson'],
    r'''
{
}''',
  );

  // Repeated strings that are long enough are pooled.
  test(
    ['Yellow', 'Blue', 'Blue', 'Crimson', 'Crimson'],
    r'''
{
  var string$ = {
    Crimso: "Crimson"
  };
}''',
  );

  // Readable property names have identical stretches compressed-out.
  var greets = [
    'Greetings Bob Smith',
    'Great work!',
    'Greetings Alice',
    'Greetings Bob Henry'
  ];

  test(
    greets * 2,
    r'''
{
  var string$ = {
    Great_: "Great work!",
    GreetiA: "Greetings Alice",
    GreetiBH: "Greetings Bob Henry",
    GreetiBS: "Greetings Bob Smith"
  };
}''',
  );

  // Non-identifiers are replaced with '_' if that is unambiguous.
  test(
    ['xylograph', '!pingpong'] * 2,
    r'''
{
  var string$ = {
    _pingp: "!pingpong",
    xylogr: "xylograph"
  };
}''',
  );

  final strings1 = [
    ...['a xylograph'] * 2,
    ...['a !pingpong'] * 4,
    ...['a %percent'] * 6,
  ];

  // Multiple discriminating non-identifier characters are replaced with an
  // escape, which causes a potentially ambiguous non-escape to be escaped.
  test(
    strings1,
    r'''
{
  var string$ = {
    a_x21pin: "a !pingpong",
    a_x25per: "a %percent",
    a_x78ylo: "a xylograph"
  };
}''',
  );

  // Minified version keeps the strings in the same order as unminified, and
  // tries to allocate the same minified name.
  const minified1 = r'''
{
  var string$ = {
    l: "a !pingpong",
    o: "a %percent",
    n: "a xylograph"
  };
}''';

  final strings2 = [
    ...['a xylograph'] * 20, // now most frequent.
    ...strings1
  ];
  test(strings1, minified1, minified: true);
  test(strings2, minified1, minified: true);
}
