// Copyright (c) 2021, 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.

/// Command line entry point for Dart Development Compiler (known as ddc,
/// dartdevc, dev compiler), used to compile a collection of dart libraries into
/// a single JS module.
library;

import 'dart:async';
import 'dart:convert';
import 'dart:developer' show Service, debugger;
import 'dart:io';
import 'dart:isolate';
import 'package:bazel_worker/bazel_worker.dart';
import 'package:kernel/ast.dart' show clearDummyTreeNodesParentPointer;

import 'src/command/arguments.dart';
import 'src/command/command.dart';
import 'src/command/result.dart';
import 'src/kernel/expression_compiler_worker.dart';

/// The internal entry point for the Dart Dev Compiler.
///
/// [sendPort] may be passed in when started in an isolate. If provided, it is
/// used for bazel worker communication instead of stdin/stdout.
Future internalMain(List<String> args, [SendPort? sendPort]) async {
  // Always returns a new modifiable list.
  var parsedArgs = ParsedArguments.from(args);

  if (parsedArgs.isWorker) {
    var workerConnection = sendPort == null
        ? StdAsyncWorkerConnection()
        : SendPortAsyncWorkerConnection(sendPort);
    await _CompilerWorker(parsedArgs, workerConnection).run();
  } else if (parsedArgs.isBatch) {
    var batch = _BatchHelper();
    await batch._runBatch(parsedArgs);
  } else if (parsedArgs.isExpressionCompiler) {
    await ExpressionCompilerWorker.createAndStart(parsedArgs.rest,
        sendPort: sendPort);
  } else {
    var result = await compile(parsedArgs);
    exitCode = result.exitCode;
  }
}

/// Runs the compiler worker loop.
class _CompilerWorker extends AsyncWorkerLoop {
  /// The original args supplied to the executable.
  final ParsedArguments _startupArgs;

  _CompilerWorker(this._startupArgs, AsyncWorkerConnection workerConnection)
      : super(connection: workerConnection);

  /// Keeps track of our last compilation result so it can potentially be
  /// re-used in a worker.
  CompilerResult? lastResult;

  /// Performs each individual work request.
  @override
  Future<WorkResponse> performRequest(WorkRequest request) async {
    var args = _startupArgs.merge(request.arguments);
    var output = StringBuffer();
    var context = args.reuseResult ? lastResult : null;

    /// Build a map of uris to digests.
    final inputDigests = <Uri, List<int>>{};
    for (var input in request.inputs) {
      inputDigests[sourcePathToUri(input.path)] = input.digest;
    }

    lastResult = await runZoned(
        () => compile(args,
            compilerState: context?.kernelState, inputDigests: inputDigests),
        zoneSpecification:
            ZoneSpecification(print: (self, parent, zone, message) {
      output.writeln(message.toString());
    }));
    return WorkResponse()
      ..exitCode = lastResult!.success ? 0 : 1
      ..output = output.toString();
  }
}

class _BatchHelper {
  Stopwatch watch = Stopwatch();
  CompilerResult? result;
  int totalTests = 0;
  int failedTests = 0;

  /// One can go into "leak test mode" by doing `export DDC_LEAK_TEST="true"`
  /// on the terminal (I think `set DDC_LEAK_TEST="true"` on Windows).
  /// Then one could run test.py, say
  /// ```
  /// python3 tools/test.py -t10000 -c ddc --nnbd weak -m release -r none \
  ///   --enable-asserts --no-use-sdk -j 1 co19/LanguageFeatures/
  /// ```
  /// and attach the leak tester via
  /// ```
  /// out/ReleaseX64/dart \
  ///   pkg/front_end/test/vm_service_for_leak_detection.dart --dart-leak-test
  /// ```
  final bool leakTesting = Platform.environment['DDC_LEAK_TEST'] == 'true';

  /// Runs DDC in Kernel batch mode for test.dart.
  Future _runBatch(ParsedArguments batchArgs) async {
    _workaroundForLeakingBug();
    if (leakTesting) {
      var services =
          await Service.controlWebServer(enable: true, silenceOutput: true);
      File.fromUri(Directory.systemTemp.uri.resolve('./dart_leak_test_uri'))
          .writeAsStringSync(services.serverUri!.toString());
    }

    watch.start();

    print('>>> BATCH START');

    String? line;
    while ((line = stdin.readLineSync(encoding: utf8))?.isNotEmpty == true) {
      await _doIteration(batchArgs, line!);
      _iterationDone();
    }

    var time = watch.elapsedMilliseconds;
    print('>>> BATCH END (${totalTests - failedTests})/$totalTests ${time}ms');
  }

  Future<void> _doIteration(ParsedArguments batchArgs, String line) async {
    totalTests++;
    var args = batchArgs.merge(line.split(RegExp(r'\s+')));

    String outcome;
    try {
      result = await compile(args, compilerState: result?.kernelState);
      outcome = result!.success ? 'PASS' : (result!.crashed ? 'CRASH' : 'FAIL');
    } catch (e, s) {
      // Clear the cache. It might have been left in a weird state.
      result = null;
      outcome = 'CRASH';
      print('Unhandled exception:');
      print(e);
      print(s);
    }

    stderr.writeln('>>> EOF STDERR');
    print('>>> TEST $outcome ${watch.elapsedMilliseconds}ms');
  }

  void _iterationDone() {
    if (leakTesting) {
      // Dummy tree nodes can (currently) leak though the parent pointer.
      // To avoid that (here) (for leak testing) we'll null them out.
      clearDummyTreeNodesParentPointer();

      print('Will now wait');
      debugger();
    }
  }

  /// Workaround for https://github.com/dart-lang/sdk/issues/51317.
  void _workaroundForLeakingBug() {
    try {
      stdin.echoMode;
    } catch (e) {/**/}
    try {
      stdout.writeln();
    } catch (e) {/**/}
    try {
      stderr.writeln();
    } catch (e) {/**/}
  }
}
