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

import 'dart:io';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/world.dart';
import 'package:expect/expect.dart';
import '../helpers/memory_compiler.dart';

enum Kind {
  regular,
  native,
  jsInterop,
}

main() {
  asyncTest(() async {
    await runTest('tests/compiler/dart2js_extra/jsinterop_test.dart', '', {
      'Class': Kind.regular,
      'JsInteropClass': Kind.jsInterop,
      'topLevelField': Kind.regular,
      'topLevelGetter': Kind.regular,
      'topLevelSetter': Kind.regular,
      'topLevelFunction': Kind.regular,
      'externalTopLevelGetter': Kind.jsInterop,
      'externalTopLevelSetter': Kind.jsInterop,
      'externalTopLevelFunction': Kind.jsInterop,
      'externalTopLevelJsInteropGetter': Kind.jsInterop,
      'externalTopLevelJsInteropSetter': Kind.jsInterop,
      'externalTopLevelJsInteropFunction': Kind.jsInterop,
      'Class.generative': Kind.regular,
      'Class.fact': Kind.regular,
      'Class.instanceField': Kind.regular,
      'Class.instanceGetter': Kind.regular,
      'Class.instanceSetter': Kind.regular,
      'Class.instanceMethod': Kind.regular,
      'Class.staticField': Kind.regular,
      'Class.staticGetter': Kind.regular,
      'Class.staticSetter': Kind.regular,
      'Class.staticMethod': Kind.regular,
      'JsInteropClass.externalGenerative': Kind.jsInterop,
      'JsInteropClass.externalFact': Kind.jsInterop,
      'JsInteropClass.externalJsInteropGenerative': Kind.jsInterop,
      'JsInteropClass.externalJsInteropFact': Kind.jsInterop,
      'JsInteropClass.externalInstanceGetter': Kind.jsInterop,
      'JsInteropClass.externalInstanceSetter': Kind.jsInterop,
      'JsInteropClass.externalInstanceMethod': Kind.jsInterop,
      'JsInteropClass.externalStaticGetter': Kind.jsInterop,
      'JsInteropClass.externalStaticSetter': Kind.jsInterop,
      'JsInteropClass.externalStaticMethod': Kind.jsInterop,
      'JsInteropClass.externalInstanceJsInteropGetter': Kind.jsInterop,
      'JsInteropClass.externalInstanceJsInteropSetter': Kind.jsInterop,
      'JsInteropClass.externalInstanceJsInteropMethod': Kind.jsInterop,
      'JsInteropClass.externalStaticJsInteropGetter': Kind.jsInterop,
      'JsInteropClass.externalStaticJsInteropSetter': Kind.jsInterop,
      'JsInteropClass.externalStaticJsInteropMethod': Kind.jsInterop,
    }, skipList: [
      // TODO(34174): Js-interop fields should not be allowed.
      '01',
      '02',
      '03',
      '04',
      '38',
      '42',
      '46',
      '51',
      // TODO(33834): Non-external constructors should not be allowed.
      '34',
      '35',
      '36',
      '37',
      // TODO(34345): Non-external static members should not be allowed.
      '43',
      '44',
      '45',
      '52',
      '53',
      '54',
    ]);
    await runTest('tests/compiler/dart2js_extra/non_jsinterop_test.dart', '', {
      'Class': Kind.regular,
      'JsInteropClass': Kind.jsInterop,
      'topLevelField': Kind.regular,
      'topLevelGetter': Kind.regular,
      'topLevelSetter': Kind.regular,
      'topLevelFunction': Kind.regular,
      'externalTopLevelJsInteropGetter': Kind.jsInterop,
      'externalTopLevelJsInteropSetter': Kind.jsInterop,
      'externalTopLevelJsInteropFunction': Kind.jsInterop,
      'Class.generative': Kind.regular,
      'Class.fact': Kind.regular,
      'Class.instanceField': Kind.regular,
      'Class.instanceGetter': Kind.regular,
      'Class.instanceSetter': Kind.regular,
      'Class.instanceMethod': Kind.regular,
      'Class.staticField': Kind.regular,
      'Class.staticGetter': Kind.regular,
      'Class.staticSetter': Kind.regular,
      'Class.staticMethod': Kind.regular,
      'JsInteropClass.externalGenerative': Kind.jsInterop,
      'JsInteropClass.externalFact': Kind.jsInterop,
      'JsInteropClass.externalJsInteropGenerative': Kind.jsInterop,
      'JsInteropClass.externalJsInteropFact': Kind.jsInterop,
      'JsInteropClass.externalInstanceGetter': Kind.jsInterop,
      'JsInteropClass.externalInstanceSetter': Kind.jsInterop,
      'JsInteropClass.externalInstanceMethod': Kind.jsInterop,
      'JsInteropClass.externalStaticGetter': Kind.jsInterop,
      'JsInteropClass.externalStaticSetter': Kind.jsInterop,
      'JsInteropClass.externalStaticMethod': Kind.jsInterop,
      'JsInteropClass.externalInstanceJsInteropGetter': Kind.jsInterop,
      'JsInteropClass.externalInstanceJsInteropSetter': Kind.jsInterop,
      'JsInteropClass.externalInstanceJsInteropMethod': Kind.jsInterop,
      'JsInteropClass.externalStaticJsInteropGetter': Kind.jsInterop,
      'JsInteropClass.externalStaticJsInteropSetter': Kind.jsInterop,
      'JsInteropClass.externalStaticJsInteropMethod': Kind.jsInterop,
    }, skipList: [
      // TODO(34174): Js-interop fields should not be allowed.
      '01',
      '02',
      '03',
      '04',
      '38',
      '42',
      '46',
      '51',
      // TODO(33834): Non-external constructors should not be allowed.
      '34',
      '35',
      '36',
      '37',
      // TODO(34345): Non-external static members should not be allowed.
      '43',
      '44',
      '45',
      '52',
      '53',
      '54',
    ]);
    // TODO(johnniwinther): Add similar test for native declarations.
  });
}

runTest(String fileName, String location, Map<String, Kind> expectations,
    {List<String> skipList: const <String>[]}) async {
  print('--------------------------------------------------------------------');
  print('Testing $fileName');
  print('--------------------------------------------------------------------');
  String test = new File(fileName).readAsStringSync();

  List<String> commonLines = <String>[];
  Map<String, SubTest> subTests = <String, SubTest>{};

  int lineIndex = 0;
  for (String line in test.split('\n')) {
    int index = line.indexOf('//#');
    if (index != -1) {
      String prefix = line.substring(0, index);
      String suffix = line.substring(index + 3);
      String name = suffix.substring(0, suffix.indexOf((':'))).trim();
      SubTest subTest = subTests.putIfAbsent(name, () => new SubTest());
      subTest.lines[lineIndex] = line;
      int commentIndex = prefix.indexOf('// ');
      if (commentIndex != -1) {
        subTest.expectedError = prefix.substring(commentIndex + 3).trim();
      }
      commonLines.add('');
    } else {
      commonLines.add(line);
    }
    lineIndex++;
  }

  String path = '${location}main.dart';
  Uri entryPoint = Uri.parse('memory:$path');
  await runPositiveTest(
      entryPoint, {path: commonLines.join('\n')}, expectations);
  for (String name in subTests.keys) {
    if (!skipList.contains(name)) {
      SubTest subTest = subTests[name];
      await runNegativeTest(
          subTest, entryPoint, {path: subTest.generateCode(commonLines)});
    }
  }
}

runPositiveTest(Uri entryPoint, Map<String, String> sources,
    Map<String, Kind> expectations) async {
  CompilationResult result =
      await runCompiler(entryPoint: entryPoint, memorySourceFiles: sources);
  Expect.isTrue(result.isSuccess);

  JClosedWorld closedWorld = result.compiler.backendClosedWorldForTesting;
  ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;

  void checkClass(ClassEntity cls,
      {bool isNative: false, bool isJsInterop: false}) {
    if (isJsInterop) {
      isNative = true;
    }
    Expect.equals(isJsInterop, closedWorld.nativeData.isJsInteropClass(cls),
        "Unexpected js interop class result for $cls.");
    Expect.equals(isNative, closedWorld.nativeData.isNativeClass(cls),
        "Unexpected native class result for $cls.");
    if (isJsInterop) {
      Expect.isTrue(closedWorld.nativeData.isJsInteropLibrary(cls.library),
          "Unexpected js interop library result for ${cls.library}.");
    }
  }

  void checkMember(MemberEntity member,
      {bool isNative: false, bool isJsInterop: false}) {
    if (isJsInterop) {
      isNative = true;
    }
    Expect.equals(isJsInterop, closedWorld.nativeData.isJsInteropMember(member),
        "Unexpected js interop member result for $member.");
    Expect.equals(isNative, closedWorld.nativeData.isNativeMember(member),
        "Unexpected native member result for $member.");
    if (isJsInterop) {
      Expect.isTrue(closedWorld.nativeData.isJsInteropLibrary(member.library),
          "Unexpected js interop library result for ${member.library}.");
    }
  }

  elementEnvironment.forEachLibraryMember(elementEnvironment.mainLibrary,
      (MemberEntity member) {
    if (member == elementEnvironment.mainFunction) return;

    Kind kind = expectations.remove(member.name);
    Expect.isNotNull(kind, "No expectations for $member");
    checkMember(member,
        isNative: kind == Kind.native, isJsInterop: kind == Kind.jsInterop);
  });

  elementEnvironment.forEachClass(elementEnvironment.mainLibrary,
      (ClassEntity cls) {
    Kind kind = expectations.remove(cls.name);
    Expect.isNotNull(kind, "No expectations for $cls");
    checkClass(cls,
        isNative: kind == Kind.native, isJsInterop: kind == Kind.jsInterop);

    checkClassMember(MemberEntity member) {
      Kind kind = expectations.remove('${cls.name}.${member.name}');
      Expect.isNotNull(kind, "No expectations for $member");
      checkMember(member,
          isNative: kind == Kind.native, isJsInterop: kind == Kind.jsInterop);
    }

    elementEnvironment.forEachConstructor(cls, checkClassMember);
    elementEnvironment.forEachLocalClassMember(cls, checkClassMember);
  });

  Expect.isTrue(expectations.isEmpty, "Untested expectations: $expectations");
}

runNegativeTest(
    SubTest subTest, Uri entryPoint, Map<String, String> sources) async {
  DiagnosticCollector collector = new DiagnosticCollector();
  CompilationResult result = await runCompiler(
      entryPoint: entryPoint,
      memorySourceFiles: sources,
      diagnosticHandler: collector);
  Expect.isFalse(result.isSuccess, "Expected compile time error for\n$subTest");
  Expect.equals(
      1, collector.errors.length, "Expected compile time error for\n$subTest");
  Expect.equals(
      'MessageKind.${subTest.expectedError}',
      collector.errors.first.messageKind.toString(),
      "Unexpected compile time error for\n$subTest");
}

class SubTest {
  String expectedError;
  final Map<int, String> lines = <int, String>{};

  String generateCode(List<String> commonLines) {
    StringBuffer sb = new StringBuffer();
    int i = 0;
    while (i < commonLines.length) {
      if (lines.containsKey(i)) {
        sb.writeln(lines[i]);
      } else {
        sb.writeln(commonLines[i]);
      }
      i++;
    }
    return sb.toString();
  }

  String toString() {
    return lines.values.join('\n');
  }
}
