// Copyright (c) 2019, 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:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
import 'package:front_end/src/api_prototype/standard_file_system.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/verifier.dart';
import 'package:vm/target/vm.dart';
import 'package:vm/kernel_front_end.dart';

main() async {
  Uri sdkSummary =
      sdkRootFile(Platform.executable).resolve('vm_platform_strong.dill');
  if (!await File.fromUri(sdkSummary).exists()) {
    // If we run from the <build-dir>/dart-sdk/bin folder, we need to navigate two
    // levels up.
    sdkSummary = sdkRootFile(Platform.executable)
        .resolve('../../vm_platform_strong.dill');
  }

  // Tests are run in the root directory of the sdk checkout.
  final Uri packagesFile = sdkRootFile('.packages');
  final Uri librariesFile = sdkRootFile('sdk/lib/libraries.json');

  final vmTarget = VmTarget(TargetFlags());

  await withTempDirectory((Uri uri) async {
    final mixinFilename = uri.resolve('mixin.dart');
    final mixinDillFilename = uri.resolve('mixin.dart.dill');
    await File.fromUri(mixinFilename).writeAsStringSync(mixinFile);

    await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
        mixinDillFilename, <Uri>[mixinFilename], <Uri>[]);

    final mainFilename = uri.resolve('main.dart');
    final mainDillFilename = uri.resolve('main.dart.dill');
    await File.fromUri(mainFilename).writeAsStringSync(mainFile);

    await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
        mainDillFilename, <Uri>[mainFilename], <Uri>[mixinDillFilename]);

    final bytes = concat(
        await File.fromUri(sdkSummary).readAsBytes(),
        concat(await File.fromUri(mixinDillFilename).readAsBytes(),
            await File.fromUri(mainDillFilename).readAsBytes()));
    final component = loadComponentFromBytes(bytes);

    // Verify before running global transformations.
    verifyComponent(component, isOutline: false, afterConst: true);

    const useGlobalTypeFlowAnalysis = true;
    const enableAsserts = false;
    const useProtobufTreeShakerV2 = false;
    await runGlobalTransformations(
        vmTarget,
        component,
        useGlobalTypeFlowAnalysis,
        enableAsserts,
        useProtobufTreeShakerV2,
        ErrorDetector());

    // Verify after running global transformations.
    verifyComponent(component, isOutline: false, afterConst: true);

    // Verify that we can reserialize the component to ensure that all
    // references are contained within the component.
    writeComponentToBytes(
        loadComponentFromBytes(writeComponentToBytes(component)));
  });
}

Future compileToKernel(
    Target target,
    Uri librariesFile,
    Uri sdkSummary,
    Uri packagesFile,
    Uri outputFile,
    List<Uri> sources,
    List<Uri> additionalDills) async {
  final state = await fe.initializeCompiler(
      null,
      sdkSummary,
      librariesFile,
      packagesFile,
      additionalDills,
      target,
      StandardFileSystem.instance, const <String>[], const <String, String>{});

  void onDiagnostic(fe.DiagnosticMessage message) {
    message.plainTextFormatted.forEach(print);
  }

  final Component component =
      await fe.compileComponent(state, sources, onDiagnostic);
  final Uint8List kernel = fe.serializeComponent(component,
      filter: (library) => sources.contains(library.importUri));
  await File(outputFile.toFilePath()).writeAsBytes(kernel);
}

Future withTempDirectory(Future func(Uri dirUri)) async {
  final dir = await Directory.systemTemp.createTemp('modular-compile-test');
  try {
    await func(dir.uri);
  } finally {
    await dir.delete(recursive: true);
  }
}

Uint8List concat(List<int> a, List<int> b) {
  final bytes = Uint8List(a.length + b.length);
  bytes.setRange(0, a.length, a);
  bytes.setRange(a.length, bytes.length, b);
  return bytes;
}

Uri sdkRootFile(name) => Directory.current.uri.resolveUri(Uri.file(name));

const String mainFile = r'''
// @dart=2.9
// This library is opt-out to provoke the creation of member signatures in
// R that point to members of A2.

import 'mixin.dart';

class R extends A2 {
  void bar() {
    mixinProperty = '';
    mixinProperty.foo();
    mixinMethod('').foo();
    super.mixinProperty= '';
    super.mixinProperty.foo();
    super.mixinMethod('').foo();
  }
}

main() {
  A1();
  final a2 = A2();
  // The mixin deduplication will remove the anonymous mixin application class
  // from `A2 & Mixin` and instead use the one from `A1 & Mixin`.
  a2.mixinProperty= '';
  a2.mixinProperty.foo();
  a2.mixinMethod('').foo();
  R().bar();
  B1();
  B1.named();
  B2();
  final b2 = B2.named();
  // The mixin deduplication will remove the anonymous mixin application class
  // from `B2 & Mixin` and instead use the one from `B1 & Mixin`.
  b2.mixinProperty= '';
  b2.mixinProperty.foo();
  b2.mixinMethod('').foo();
}
''';

const String mixinFile = r'''
class Foo {
  foo() {}
}
class Mixin {
  void set mixinProperty(v) {}
  Foo get mixinProperty => new Foo();
  Foo mixinMethod(v) => new Foo();
}
class A1 extends Object with Mixin { }
class A2 extends Object with Mixin { }
class B {
   B();
   B.named();
}
class B1 extends B with Mixin {
  B1() : super();
  B1.named() : super.named();
}
class B2 extends B with Mixin {
  B2() : super();
  B2.named() : super.named();
}
''';
