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

// @dart = 2.7

// Test that the enqueuers are not dependent upon in which order impacts are
// applied.

import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common/elements.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/elements/names.dart';
import 'package:compiler/src/elements/types.dart';
import 'package:compiler/src/enqueue.dart';
import 'package:compiler/src/inferrer/typemasks/masks.dart';
import 'package:compiler/src/universe/call_structure.dart';
import 'package:compiler/src/universe/selector.dart';
import 'package:compiler/src/universe/world_impact.dart';
import 'package:compiler/src/universe/use.dart';
import 'package:compiler/src/universe/world_builder.dart';
import 'package:compiler/src/js_model/js_world.dart' show JClosedWorld;
import 'package:expect/expect.dart';
import '../helpers/memory_compiler.dart';

class Test {
  final String name;
  final String code;
  final List<Impact> impacts;
  final Map<String, List<String>> expectedLiveMap;

  const Test({this.name, this.code, this.impacts, this.expectedLiveMap});

  Map<String, List<String>> get expectedLiveResolutionMap {
    Map<String, List<String>> map = {};
    expectedLiveMap.forEach((String clsName, List<String> memberNames) {
      for (String memberName in memberNames) {
        if (memberName.startsWith('?')) {
          memberName = memberName.substring(1);
        }
        map.putIfAbsent(clsName, () => []).add(memberName);
      }
    });
    return map;
  }

  Map<String, List<String>> get expectedLiveCodegenMap {
    Map<String, List<String>> map = {};
    expectedLiveMap.forEach((String clsName, List<String> memberNames) {
      for (String memberName in memberNames) {
        if (memberName.startsWith('?')) {
          // Skip for codegen
          continue;
        }
        map.putIfAbsent(clsName, () => []).add(memberName);
      }
    });
    return map;
  }
}

enum ImpactKind { instantiate, invoke }

class Impact {
  final ImpactKind kind;
  final String clsName;
  final String memberName;

  const Impact.instantiate(this.clsName, [this.memberName = ''])
      : this.kind = ImpactKind.instantiate;
  const Impact.invoke(this.clsName, this.memberName)
      : this.kind = ImpactKind.invoke;

  @override
  String toString() =>
      'Impact(kind=$kind,clsName=$clsName,memberName=$memberName)';
}

const List<Test> tests = const <Test>[
  const Test(name: 'Instantiate class', code: '''
class A {
  void method() {}
}
''', impacts: const [
    const Impact.instantiate('A'),
    const Impact.invoke('A', 'method'),
  ], expectedLiveMap: const {
    'A': const ['', 'method'],
  }),
  const Test(name: 'Instantiate subclass', code: '''
class A {
  void method() {}
}
class B extends A {
}
''', impacts: const [
    const Impact.instantiate('B'),
    const Impact.invoke('B', 'method'),
  ], expectedLiveMap: const {
    'A': const ['?', 'method'],
    'B': const [''],
  }),
  const Test(name: 'Instantiate superclass/subclass', code: '''
class A {
  void method() {}
}
class B extends A {
}
''', impacts: const [
    const Impact.instantiate('A'),
    const Impact.instantiate('B'),
    const Impact.invoke('B', 'method'),
  ], expectedLiveMap: const {
    'A': const ['', 'method'],
    'B': const [''],
  }),
];

main() {
  asyncTest(() async {
    for (Test test in tests) {
      await runTest(test);
    }
  });
}

runTest(Test test) async {
  print('====================================================================');
  print('Running test ${test.name}');
  for (List<Impact> permutation in permutations(test.impacts)) {
    print('------------------------------------------------------------------');
    print('Permutation: $permutation');
    await runTestPermutation(test, permutation);
  }
}

Iterable<List<Impact>> permutations(List<Impact> impacts) sync* {
  int length = impacts.length;
  if (length <= 1) {
    yield impacts;
  } else {
    for (int index = 0; index < length; index++) {
      Impact head = impacts[index];
      List<Impact> tail = new List<Impact>.from(impacts)..removeAt(index);
      for (List<Impact> permutation in permutations(tail)) {
        yield [head]..addAll(permutation);
      }
    }
  }
}

runTestPermutation(Test test, List<Impact> impacts) async {
  Compiler compiler = compilerFor(memorySourceFiles: {
    'main.dart': '''
${test.code}
main() {}
'''
  }, options: [
    Flags.disableInlining,
  ], entryPoint: Uri.parse('memory:main.dart'));

  void checkInvariant(
      Enqueuer enqueuer, ElementEnvironment elementEnvironment) {
    for (MemberEntity member
        in compiler.resolutionEnqueuerForTesting.processedEntities) {
      Expect.isTrue(
          member == elementEnvironment.mainFunction ||
              member.library != elementEnvironment.mainLibrary,
          "Unexpected member $member in ${enqueuer}.");
    }
  }

  void instantiate(
      Enqueuer enqueuer, ElementEnvironment elementEnvironment, String name) {
    ClassEntity cls =
        elementEnvironment.lookupClass(elementEnvironment.mainLibrary, name);
    ConstructorEntity constructor =
        elementEnvironment.lookupConstructor(cls, '');
    InterfaceType type = elementEnvironment.getRawType(cls);
    WorldImpact impact = new WorldImpactBuilderImpl()
      ..registerStaticUse(new StaticUse.typedConstructorInvoke(constructor,
          constructor.parameterStructure.callStructure, type, null));
    enqueuer.applyImpact(impact);
  }

  void invoke(
      Enqueuer enqueuer,
      ElementEnvironment elementEnvironment,
      String className,
      String methodName,
      Object Function(ClassEntity cls) createConstraint) {
    ClassEntity cls = elementEnvironment.lookupClass(
        elementEnvironment.mainLibrary, className);
    Selector selector = new Selector.call(
        new Name(methodName, elementEnvironment.mainLibrary.canonicalUri),
        CallStructure.NO_ARGS);
    WorldImpact impact = new WorldImpactBuilderImpl()
      ..registerDynamicUse(
          new DynamicUse(selector, createConstraint(cls), const <DartType>[]));
    enqueuer.applyImpact(impact);
  }

  void applyImpact(Enqueuer enqueuer, ElementEnvironment elementEnvironment,
      Impact impact, Object Function(ClassEntity cls) createConstraint) {
    switch (impact.kind) {
      case ImpactKind.instantiate:
        instantiate(enqueuer, elementEnvironment, impact.clsName);
        break;
      case ImpactKind.invoke:
        invoke(enqueuer, elementEnvironment, impact.clsName, impact.memberName,
            createConstraint);
        break;
    }
  }

  void checkLiveMembers(
      Enqueuer enqueuer,
      ElementEnvironment elementEnvironment,
      Map<String, List<String>> expectedLiveMap) {
    Map<String, List<String>> actualLiveMap = {};
    for (MemberEntity member in enqueuer.processedEntities) {
      if (member != elementEnvironment.mainFunction &&
          member.library == elementEnvironment.mainLibrary) {
        actualLiveMap
            .putIfAbsent(member.enclosingClass.name, () => [])
            .add(member.name);
      }
    }

    Expect.setEquals(
        expectedLiveMap.keys,
        actualLiveMap.keys,
        "Unexpected live classes in $enqueuer\n "
        "Expected: ${expectedLiveMap.keys}\n "
        "Actual  : ${actualLiveMap.keys}");
    expectedLiveMap.forEach((String clsName, List<String> expectedMembers) {
      List<String> actualMembers = actualLiveMap[clsName];
      Expect.setEquals(
          expectedMembers,
          actualMembers,
          "Unexpected live members for $clsName in $enqueuer\n "
          "Expected: $expectedMembers\n "
          "Actual  : $actualMembers");
    });
  }

  compiler.onResolutionQueueEmptyForTesting = () {
    Enqueuer enqueuer = compiler.resolutionEnqueuerForTesting;
    ElementEnvironment elementEnvironment =
        compiler.frontendStrategy.elementEnvironment;
    checkInvariant(enqueuer, elementEnvironment);

    Object createConstraint(ClassEntity cls) {
      return new StrongModeConstraint(compiler.frontendStrategy.commonElements,
          compiler.frontendStrategy.elementMap.nativeBasicData, cls);
    }

    for (Impact impact in impacts) {
      applyImpact(enqueuer, elementEnvironment, impact, createConstraint);
    }
  };
  compiler.onCodegenQueueEmptyForTesting = () {
    Enqueuer enqueuer = compiler.codegenEnqueuerForTesting;
    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
    ElementEnvironment elementEnvironment =
        compiler.backendClosedWorldForTesting.elementEnvironment;
    checkInvariant(enqueuer, elementEnvironment);

    Object createConstraint(ClassEntity cls) {
      return new TypeMask.subtype(cls, closedWorld);
    }

    for (Impact impact in impacts) {
      applyImpact(enqueuer, elementEnvironment, impact, createConstraint);
    }
  };

  await compiler.run();

  checkLiveMembers(
      compiler.resolutionEnqueuerForTesting,
      compiler.frontendStrategy.elementEnvironment,
      test.expectedLiveResolutionMap);

  checkLiveMembers(
      compiler.codegenEnqueuerForTesting,
      compiler.backendClosedWorldForTesting.elementEnvironment,
      test.expectedLiveCodegenMap);
}
