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

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

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_builder.dart';
import 'package:compiler/src/universe/world_impact.dart';
import 'package:compiler/src/universe/use.dart';
import 'package:compiler/src/js_model/js_world.dart' show JClosedWorld;
import 'package:expect/async_helper.dart';
import 'package:expect/expect.dart';
import 'package:compiler/src/util/memory_compiler.dart';

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

  const Test({
    required this.name,
    required this.code,
    required this.impacts,
    required 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 = 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 enqueuer.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 =
        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 = Selector.call(
      Name(methodName, elementEnvironment.mainLibrary!.canonicalUri),
      CallStructure.noArgs,
    );
    WorldImpact impact =
        WorldImpactBuilderImpl()..registerDynamicUse(
          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 defaultReceiverClass(
        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 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,
  );
}
