// 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 'package:shell_arg_splitter/shell_arg_splitter.dart';

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(splitLine(line, windows: Platform.isWindows));

    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) {
      /**/
    }
  }
}
