// 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> {
  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);
}
