// 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/entities_parameter_structure_methods.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/world.dart';
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),
        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);
}
