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

import 'dart:io' show File;

import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
    show DiagnosticMessage, getMessageCodeObject;

import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;

import 'package:expect/expect.dart' show Expect;

import 'package:front_end/src/api_prototype/compiler_options.dart'
    show CompilerOptions;

import 'package:front_end/src/api_prototype/experimental_flags.dart'
    show ExperimentalFlag;

import "package:front_end/src/api_prototype/memory_file_system.dart"
    show MemoryFileSystem;

import 'package:front_end/src/base/nnbd_mode.dart' show NnbdMode;

import 'package:front_end/src/base/processed_options.dart'
    show ProcessedOptions;

import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation;

import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;

import 'package:front_end/src/fasta/fasta_codes.dart'
    show
        Code,
        codeInitializeFromDillNotSelfContained,
        codeInitializeFromDillNotSelfContainedNoDump,
        codeInitializeFromDillUnknownProblem,
        codeInitializeFromDillUnknownProblemNoDump;

import 'package:front_end/src/fasta/incremental_compiler.dart'
    show IncrementalCompiler;

import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;

import 'package:kernel/kernel.dart'
    show Component, Library, NonNullableByDefaultCompiledMode;

import 'incremental_suite.dart' show getOptions;

Future<Null> main() async {
  Tester tester = new Tester();
  await tester.initialize();
  await tester.test();
}

class Tester {
  Uri sdkRoot;
  Uri base;
  Uri sdkSummary;
  Uri initializeFrom;
  Uri helperFile;
  Uri helper2File;
  Uri entryPoint;
  Uri entryPointImportDartFoo;
  Uri platformUri;
  List<int> sdkSummaryData;
  List<DiagnosticMessage> errorMessages;
  List<DiagnosticMessage> warningMessages;
  MemoryFileSystem fs;
  CompilerOptions options;
  IncrementalCompiler compiler;

  Future<void> compileExpectInitializeFailAndSpecificWarning(
      Code expectedWarningCode, bool writeFileOnCrashReport) async {
    errorMessages.clear();
    warningMessages.clear();
    options.writeFileOnCrashReport = writeFileOnCrashReport;
    compiler = new DeleteTempFilesIncrementalCompiler(
        new CompilerContext(
            new ProcessedOptions(options: options, inputs: [entryPoint])),
        initializeFrom);
    await compiler.computeDelta();
    if (compiler.initializedFromDill) {
      Expect.fail("Expected to not be able to initialized from dill, but did.");
    }
    if (errorMessages.isNotEmpty) {
      Expect.fail("Got unexpected errors: " + joinMessages(errorMessages));
    }
    if (warningMessages.length != 1) {
      Expect.fail("Got unexpected errors: Expected one, got this: " +
          joinMessages(warningMessages));
    }
    if (getMessageCodeObject(warningMessages[0]) != expectedWarningCode) {
      Expect.fail("Expected ${expectedWarningCode.name} but got " +
          joinMessages(warningMessages));
    }
  }

  Future<Component> compileExpectOk(
      bool initializedFromDill, Uri compileThis) async {
    errorMessages.clear();
    warningMessages.clear();
    options.writeFileOnCrashReport = false;
    compiler = new DeleteTempFilesIncrementalCompiler(
        new CompilerContext(
            new ProcessedOptions(options: options, inputs: [compileThis])),
        initializeFrom);
    Component component = await compiler.computeDelta();

    if (compiler.initializedFromDill != initializedFromDill) {
      Expect.fail("Expected initializedFromDill to be $initializedFromDill "
          "but was ${compiler.initializedFromDill}");
    }
    if (errorMessages.isNotEmpty) {
      Expect.fail("Got unexpected errors: " + joinMessages(errorMessages));
    }
    if (warningMessages.isNotEmpty) {
      Expect.fail("Got unexpected warnings: " + joinMessages(warningMessages));
    }

    return component;
  }

  Future<void> initialize() async {
    sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
    base = Uri.parse("org-dartlang-test:///");
    sdkSummary = base.resolve("vm_platform.dill");
    initializeFrom = base.resolve("initializeFrom.dill");
    helperFile = base.resolve("helper.dart");
    helper2File = base.resolve("helper2.dart");
    entryPoint = base.resolve("small.dart");
    entryPointImportDartFoo = base.resolve("small_foo.dart");
    platformUri = sdkRoot.resolve("vm_platform_strong.dill");
    sdkSummaryData = await new File.fromUri(platformUri).readAsBytes();
    errorMessages = <DiagnosticMessage>[];
    warningMessages = <DiagnosticMessage>[];
    fs = new MemoryFileSystem(base);
    options = getOptions();

    options.fileSystem = fs;
    options.sdkRoot = null;
    options.sdkSummary = sdkSummary;
    options.omitPlatform = true;
    options.onDiagnostic = (DiagnosticMessage message) {
      if (message.severity == Severity.error) {
        errorMessages.add(message);
      } else if (message.severity == Severity.warning) {
        warningMessages.add(message);
      }
    };

    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
    fs.entityForUri(helperFile).writeAsStringSync("""
foo() {
    print("hello from foo");
}
""");
    fs.entityForUri(helper2File).writeAsStringSync("""
foo2() {
    print("hello from foo2");
}
""");
    fs.entityForUri(entryPoint).writeAsStringSync("""
import "helper.dart" as helper;
main() {
    helper.foo();
}
""");
    fs.entityForUri(entryPointImportDartFoo).writeAsStringSync("""
import "dart:foo" as helper;
main() {
    helper.foo2();
}
""");
  }

  Future<Null> test() async {
    compiler = new IncrementalCompiler(
        new CompilerContext(
            new ProcessedOptions(options: options, inputs: [entryPoint])),
        initializeFrom);

    Component componentGood = await compiler.computeDelta();
    List<int> dataGood = serializeComponent(componentGood);
    fs.entityForUri(initializeFrom).writeAsBytesSync(dataGood);

    // Create fake "dart:foo" library.
    options.omitPlatform = false;
    compiler = new IncrementalCompiler(
        new CompilerContext(
            new ProcessedOptions(options: options, inputs: [helper2File])),
        initializeFrom);
    Component componentHelper = await compiler.computeDelta();
    Library helper2Lib = componentHelper.libraries
        .firstWhere((lib) => lib.importUri == helper2File);
    helper2Lib.importUri = new Uri(scheme: "dart", path: "foo");
    List<int> sdkWithDartFoo = serializeComponent(componentHelper);
    options.omitPlatform = true;

    // Compile with our fake sdk with dart:foo should be ok.
    List<int> orgSdkBytes = await fs.entityForUri(sdkSummary).readAsBytes();
    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkWithDartFoo);
    Component component = await compileExpectOk(true, entryPointImportDartFoo);
    fs.entityForUri(sdkSummary).writeAsBytesSync(orgSdkBytes);
    if (component.libraries.length != 1) {
      Expect.fail("Expected 1 library, got ${component.libraries.length}: "
          "${component.libraries}");
    }
    List<int> dataLinkedToSdkWithFoo = serializeComponent(component);

    // Initialize from good dill file should be ok.
    await compileExpectOk(true, entryPoint);

    // Create a partial dill file.
    compiler.invalidate(entryPoint);
    component = await compiler.computeDelta();
    if (component.libraries.length != 1) {
      Expect.fail("Expected 1 library, got ${component.libraries.length}: "
          "${component.libraries}");
    }
    List<int> data = serializeComponent(component);
    fs.entityForUri(initializeFrom).writeAsBytesSync(data);

    // Initializing from partial dill should not be ok.
    await compileExpectInitializeFailAndSpecificWarning(
        codeInitializeFromDillNotSelfContained, true);
    await compileExpectInitializeFailAndSpecificWarning(
        codeInitializeFromDillNotSelfContainedNoDump, false);

    // Create a invalid dill file to load from: Should not be ok.
    data = new List<int>.filled(42, 42);
    fs.entityForUri(initializeFrom).writeAsBytesSync(data);
    await compileExpectInitializeFailAndSpecificWarning(
        codeInitializeFromDillUnknownProblem, true);
    await compileExpectInitializeFailAndSpecificWarning(
        codeInitializeFromDillUnknownProblemNoDump, false);

    // Create a dill with a reference to a non-existing sdk thing:
    // Should be ok (for now), but we shouldn't actually initialize from dill.
    fs.entityForUri(initializeFrom).writeAsBytesSync(dataLinkedToSdkWithFoo);
    await compileExpectOk(false, entryPoint);

    // Try to initialize from a dill which contains mixed compilation modes:
    // Should be ok, but we shouldn't actually initialize from dill.
    List<int> mixedPart1;
    {
      // Create a component that is compiled without NNBD.
      Map<ExperimentalFlag, bool> prevTesting =
          options.defaultExperimentFlagsForTesting;
      options.defaultExperimentFlagsForTesting = {
        ExperimentalFlag.nonNullable: false
      };
      NnbdMode prevNnbd = options.nnbdMode;
      options.nnbdMode = NnbdMode.Weak;
      compiler = new IncrementalCompiler(
          new CompilerContext(
              new ProcessedOptions(options: options, inputs: [helper2File])),
          null);
      Component c = await compiler.computeDelta();
      c.setMainMethodAndMode(
          null, false, NonNullableByDefaultCompiledMode.Weak);
      mixedPart1 = serializeComponent(c);
      options.defaultExperimentFlagsForTesting = prevTesting;
      options.nnbdMode = prevNnbd;
    }

    List<int> mixedPart2;
    {
      // Create a component that is compiled with strong NNBD.
      Map<ExperimentalFlag, bool> prevTesting =
          options.defaultExperimentFlagsForTesting;
      options.defaultExperimentFlagsForTesting = {
        ExperimentalFlag.nonNullable: true
      };
      NnbdMode prevNnbd = options.nnbdMode;
      options.nnbdMode = NnbdMode.Strong;
      compiler = new IncrementalCompiler(
          new CompilerContext(
              new ProcessedOptions(options: options, inputs: [helperFile])),
          null);
      Component c = await compiler.computeDelta();
      c.setMainMethodAndMode(
          null, false, NonNullableByDefaultCompiledMode.Strong);
      mixedPart2 = serializeComponent(c);
      options.defaultExperimentFlagsForTesting = prevTesting;
      options.nnbdMode = prevNnbd;
    }

    // Now mix the two components together and try to initialize from them.
    // We expect the compilation to be OK but that the dill is not actually
    // used to initialize from (as it's invalid because of the mixed mode).
    List<int> mixed = [];
    mixed.addAll(mixedPart1);
    mixed.addAll(mixedPart2);
    fs.entityForUri(initializeFrom).writeAsBytesSync(mixed);
    await compileExpectOk(false, entryPoint);
  }
}

class DeleteTempFilesIncrementalCompiler extends IncrementalCompiler {
  DeleteTempFilesIncrementalCompiler(CompilerContext context,
      [Uri initializeFromDillUri])
      : super(context, initializeFromDillUri);

  @override
  void recordTemporaryFileForTesting(Uri uri) {
    File f = new File.fromUri(uri);
    if (f.existsSync()) f.deleteSync();
  }
}

String joinMessages(List<DiagnosticMessage> messages) {
  return messages.map((m) => m.plainTextFormatted.join("\n")).join("\n");
}
