// Copyright 2022 The Chromium Authors. 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:convert';
import 'dart:io'
    show
        exit,
        File,
        InternetAddress,
        Link,
        Platform,
        ProcessSignal,
        ServerSocket,
        Socket;
import 'dart:typed_data' show Uint8List;

import 'package:args/args.dart';

// front_end/src imports below that require lint `ignore_for_file`
// are a temporary state of things until frontend team builds better api
// that would replace api used below. This api was made private in
// an effort to discourage further use.
// ignore_for_file: implementation_imports
import 'package:front_end/src/api_unstable/vm.dart';

import '../frontend_server.dart';

/// Floor the system time by this amount in order to correctly detect modified
/// source files on all platforms. This has no effect on correctness,
/// but may result in more files being marked as modified than strictly
/// required.
const _STAT_GRANULARITY = const Duration(seconds: 1);

const RESIDENT_SERVER_LINK_POSTFIX = '_link';

/// Ensures the symbolic link is removed if ctrl-C is sent to the server.
/// Mostly used when debugging.
StreamSubscription<ProcessSignal> _cleanupHandler;

extension on DateTime {
  /// Truncates by [amount].
  ///
  /// This is needed because the 1 second granularity on DateTime objects
  /// returned by file stat on Windows is different than the system time's
  /// granularity. We must floor the system time
  /// by 1 second so that if a file is modified within the same second of
  /// the last compile time, it will be correctly detected as being modified.
  DateTime floorTime({Duration amount = _STAT_GRANULARITY}) {
    return DateTime.fromMillisecondsSinceEpoch(this.millisecondsSinceEpoch -
        this.millisecondsSinceEpoch % amount.inMilliseconds);
  }
}

enum _ResidentState {
  WAITING_FOR_FIRST_COMPILE,
  COMPILING,
  WAITING_FOR_RECOMPILE,
}

/// A wrapper around the FrontendCompiler, along with all the state needed
/// to perform incremental compilations
///
/// TODO: Fix the race condition that occurs when the ResidentCompiler returns
///   a kernel file to the CLI and another compilation request is given before
///   the VM is able to launch from the kernel that was returned in the first
///   compile request. The ResidentCompiler will be in the state of waiting for
///   a recompile request and will subsequently process the request and modify
///   the kernel file. However, it should be waiting for the VM to finish
///   launching itself from this kernel until it modifies the kernel.
///   As far as I can tell this race also exists in the current CLI run
///   command when using pub's precompile pipeline.
///
/// TODO Fix the race condition that occurs when the same entry point is
///   compiled concurrently.
class ResidentCompiler {
  File _entryPoint;
  File _outputDill;
  File _currentPackage;
  ArgResults _compileOptions;
  FrontendCompiler _compiler;
  DateTime _lastCompileStartTime = DateTime.now().floorTime();
  _ResidentState _state = _ResidentState.WAITING_FOR_FIRST_COMPILE;
  final StringBuffer _compilerOutput = StringBuffer();
  final Set<Uri> trackedSources = <Uri>{};
  final List<String> _formattedOutput = <String>[];
  var incrementalMode = false;

  ResidentCompiler(this._entryPoint, this._outputDill, this._compileOptions) {
    _compiler = FrontendCompiler(_compilerOutput);
    updateState(_compileOptions);
  }

  /// The [ResidentCompiler] will use the [newOptions] for future compilation
  /// requests.
  void updateState(ArgResults newOptions) {
    final packages = newOptions['packages'];
    incrementalMode = newOptions['incremental'] == true;
    _compileOptions = newOptions;
    _currentPackage = packages == null ? null : File(packages);
    // Refresh the compiler's output for the next compile
    _compilerOutput.clear();
    _formattedOutput.clear();
    _state = _ResidentState.WAITING_FOR_FIRST_COMPILE;
  }

  /// The current compiler options are outdated when any option has changed
  /// since the last compile, or when the packages file has been modified
  bool areOptionsOutdated(ArgResults newOptions) {
    if (newOptions.arguments.length != _compileOptions.arguments.length) {
      return true;
    }
    if (!newOptions.arguments
        .toSet()
        .containsAll(_compileOptions.arguments.toSet())) {
      return true;
    }
    return _currentPackage != null &&
        !_lastCompileStartTime
            .isAfter(_currentPackage.statSync().modified.floorTime());
  }

  /// Compiles the entry point that this ResidentCompiler is hooked to.
  /// Will perform incremental compilations when possible.
  /// If the options are outdated, must use updateState to get a correct
  /// compile.
  Future<String> compile() async {
    var incremental = false;

    // If this entrypoint was previously compiled on this compiler instance,
    // check which source files need to be recompiled in the incremental
    // compilation request. If no files have been modified, we can return
    // the cached kernel. Otherwise, perform an incremental compilation.
    if (_state == _ResidentState.WAITING_FOR_RECOMPILE) {
      var invalidatedUris =
          await _getSourceFilesToRecompile(_lastCompileStartTime);
      // No changes to source files detected and cached kernel file exists
      // If a kernel file is removed in between compilation requests,
      // fall through to procude the kernel in recompileDelta.
      if (invalidatedUris.isEmpty && _outputDill.existsSync()) {
        return _encodeCompilerOutput(
            _outputDill.path, _formattedOutput, _compiler.errors.length,
            usingCachedKernel: true);
      }
      _state = _ResidentState.COMPILING;
      incremental = true;
      invalidatedUris
          .forEach((invalidatedUri) => _compiler.invalidate(invalidatedUri));
      _compiler.errors.clear();
      _lastCompileStartTime = DateTime.now().floorTime();
      await _compiler.recompileDelta(entryPoint: _entryPoint.path);
    } else {
      _state = _ResidentState.COMPILING;
      _lastCompileStartTime = DateTime.now().floorTime();
      _compiler.errors.clear();
      await _compiler.compile(_entryPoint.path, _compileOptions);
    }

    _interpretCompilerOutput(LineSplitter()
        .convert(_compilerOutput.toString())
        .where((line) => line.isNotEmpty)
        .toList());
    _compilerOutput.clear();

    if (incrementalMode) {
      // forces the compiler to produce complete kernel files on each
      // request, even when incrementally compiled.
      _compiler
        ..acceptLastDelta()
        ..resetIncrementalCompiler();
      _state = _ResidentState.WAITING_FOR_RECOMPILE;
    } else {
      _state = _ResidentState.WAITING_FOR_FIRST_COMPILE;
    }
    return _encodeCompilerOutput(
        _outputDill.path, _formattedOutput, _compiler.errors.length,
        incrementalCompile: incremental);
  }

  /// Reads the compiler's [outputLines] to keep track of which files
  /// need to be tracked. Adds correctly ANSI formatted output to
  /// the [_formattedOutput] list.
  void _interpretCompilerOutput(List<String> outputLines) {
    _formattedOutput.clear();
    var outputLineIndex = 0;
    var acceptingErrorsOrVerboseOutput = true;
    final boundaryKey = outputLines[outputLineIndex]
        .substring(outputLines[outputLineIndex++].indexOf(' ') + 1);
    var line = outputLines[outputLineIndex++];

    while (acceptingErrorsOrVerboseOutput || !line.startsWith(boundaryKey)) {
      if (acceptingErrorsOrVerboseOutput) {
        if (line == boundaryKey) {
          acceptingErrorsOrVerboseOutput = false;
        } else {
          _formattedOutput.add(line);
        }
      } else {
        final diffUri = line.substring(1);
        if (line.startsWith('+')) {
          trackedSources.add(Uri.parse(diffUri));
        } else if (line.startsWith('-')) {
          trackedSources.remove(Uri.parse(diffUri));
        }
      }
      line = outputLines[outputLineIndex++];
    }
  }

  /// Returns a list of uris that need to be recompiled, based on the
  /// [lastkernelCompileTime] timestamp.
  /// Due to Windows timestamp granularity, all timestamps are truncated by
  /// the second. This has no effect on correctness but may result in more
  /// files being marked as invalid than are strictly required.
  Future<List<Uri>> _getSourceFilesToRecompile(
      DateTime lastKernelCompileTime) async {
    final sourcesToRecompile = <Uri>[];
    for (Uri uri in trackedSources) {
      final sourceModifiedTime =
          File(uri.toFilePath()).statSync().modified.floorTime();
      if (!lastKernelCompileTime.isAfter(sourceModifiedTime)) {
        sourcesToRecompile.add(uri);
      }
    }
    return sourcesToRecompile;
  }

  /// Encodes [outputDillPath] and any [formattedErrors] in JSON to
  /// be sent over the socket.
  static String _encodeCompilerOutput(
    String outputDillPath,
    List<String> formattedErrors,
    int errorCount, {
    bool usingCachedKernel = false,
    bool incrementalCompile = false,
  }) {
    return jsonEncode(<String, Object>{
      "success": errorCount == 0,
      "errorCount": errorCount,
      "compilerOutputLines": formattedErrors,
      "output-dill": outputDillPath,
      if (usingCachedKernel) "returnedStoredKernel": true, // used for testing
      if (incrementalCompile) "incremental": true, // used for testing
    });
  }
}

/// Maintains [FrontendCompiler] instances for kernel compilations, meant to be
/// used by the Dart CLI via sockets.
///
/// The [ResidentFrontendServer] manages compilation requests for VM targets
/// between any number of dart entrypoints, and utilizes incremental
/// compilation and existing kernel files for faster compile times.
///
/// Communication is handled on the socket set up by the
/// residentListenAndCompile method.
class ResidentFrontendServer {
  static const _commandString = 'command';
  static const _executableString = 'executable';
  static const _packageString = 'packages';
  static const _outputString = 'output-dill';
  static const _shutdownString = 'shutdown';
  static const _compilerLimit = 3;

  static final shutdownCommand =
      jsonEncode(<String, Object>{_commandString: _shutdownString});
  static final _shutdownJsonResponse =
      jsonEncode(<String, Object>{_shutdownString: true});
  static final _sdkBinariesUri = computePlatformBinariesLocation();
  static final _sdkUri = _sdkBinariesUri.resolve('../../');
  static final _platformKernelUri =
      _sdkBinariesUri.resolve('vm_platform_strong.dill');
  static final Map<String, ResidentCompiler> compilers = {};

  /// Takes in JSON [input] from the socket and compiles the request,
  /// using incremental compilation if possible. Returns a JSON string to be
  /// sent back to the client socket containing either an error message or the
  /// kernel file to be used.
  ///
  /// If the command is compile, paths the source file, package_config.json,
  /// and the output-dill file must be provided via "executable", "packages",
  /// and "output-dill".
  static Future<String> handleRequest(String input) async {
    Map<String, dynamic> request;
    try {
      request = jsonDecode(input);
    } on FormatException {
      return _encodeErrorMessage('$input is not valid JSON.');
    }

    switch (request[_commandString]) {
      case 'compile':
        if (request[_executableString] == null ||
            request[_outputString] == null) {
          return _encodeErrorMessage(
              'compilation requests must include an $_executableString '
              'and an $_outputString path.');
        }
        final executablePath = request[_executableString];
        final cachedDillPath = request[_outputString];
        final options = _generateCompilerOptions(request);

        var residentCompiler = compilers[executablePath];
        if (residentCompiler == null) {
          // Avoids using too much memory
          if (compilers.length >= ResidentFrontendServer._compilerLimit) {
            compilers.remove(compilers.keys.first);
          }
          residentCompiler = ResidentCompiler(
              File(executablePath), File(cachedDillPath), options);
          compilers[executablePath] = residentCompiler;
        } else if (residentCompiler.areOptionsOutdated(options)) {
          residentCompiler.updateState(options);
        }

        return await residentCompiler.compile();
      case 'shutdown':
        return _shutdownJsonResponse;
      default:
        return _encodeErrorMessage(
            'Unsupported command: ${request[_commandString]}.');
    }
  }

  /// Generates the compiler options needed to satisfy the [request]
  static ArgResults _generateCompilerOptions(Map<String, dynamic> request) {
    return argParser.parse(<String>[
      '--sdk-root=${_sdkUri.toFilePath()}',
      if (!request.containsKey('aot')) '--incremental',
      '--platform=${_platformKernelUri.path}',
      '--output-dill=${request[_outputString]}',
      '--target=vm',
      '--filesystem-scheme',
      'org-dartlang-root',
      if (request.containsKey(_packageString))
        '--packages=${request[_packageString]}',
      if (request['support-mirrors'] ?? false) '--support-mirrors',
      if (request['enable-asserts'] ?? false) '--enable-asserts',
      if (request['sound-null-safety'] ?? false) '--sound-null-safety',
      if (request['verbosity'] != null) '--verbosity=${request["verbosity"]}',
      if (request['verbose'] ?? false) '--verbose',
      if (request['aot'] ?? false) '--aot',
      if (request['tfa'] ?? false) '--tfa',
      if (request['rta'] ?? false) '--rta',
      if (request['tree-shake-write-only-fields'] ?? false)
        '--tree-shake-write-only-fields',
      if (request['protobuf-tree-shaker-v2'] ?? false)
        '--protobuf-tree-shaker-v2',
      if (request['define'] != null)
        for (var define in request['define']) define,
      if (request['enable-experiement'] != null)
        for (var experiment in request['enable-experiment']) experiment,
    ]);
  }

  /// Encodes the [message] in JSON to be sent over the socket.
  static String _encodeErrorMessage(String message) =>
      jsonEncode(<String, Object>{"success": false, "errorMessage": message});

  /// Used to create compile requests for the ResidentFrontendServer.
  /// Returns a JSON string that the resident compiler will be able to
  /// interpret.
  static String createCompileJSON(
      {String executable,
      String packages,
      String outputDill,
      bool supportMirrors,
      bool enableAsserts,
      bool soundNullSafety,
      String verbosity,
      bool aot,
      bool tfa,
      bool rta,
      bool treeShakeWriteOnlyFields,
      bool protobufTreeShakerV2,
      List<String> define,
      List<String> enableExperiement,
      bool verbose = false}) {
    return jsonEncode(<String, Object>{
      "command": "compile",
      "executable": executable,
      "output-dill": outputDill,
      if (aot != null) "aot": true,
      if (define != null) "define": define,
      if (enableAsserts != null) "enable-asserts": true,
      if (enableExperiement != null) "enable-experiment": enableExperiement,
      if (packages != null) "packages": packages,
      if (protobufTreeShakerV2 != null) "protobuf-tree-shaker-v2": true,
      if (rta != null) "rta": true,
      if (soundNullSafety != null) "sound-null-safety": soundNullSafety,
      if (supportMirrors != null) "support-mirrors": true,
      if (tfa != null) "tfa": true,
      if (treeShakeWriteOnlyFields != null)
        "tree-shaker-write-only-fields": true,
      if (verbosity != null) "verbosity": verbosity,
      "verbose": verbose,
    });
  }
}

/// Sends the JSON string [request] to the resident frontend server
/// and returns server's response in JSON
///
/// Clients must use this function when wanting to interact with a
/// ResidentFrontendServer instance.
Future<Map<String, dynamic>> sendAndReceiveResponse(
    InternetAddress address, int port, String request) async {
  Socket client;
  Map<String, dynamic> jsonResponse;
  try {
    client = await Socket.connect(address, port);
    client.write(request);
    final data = String.fromCharCodes(await client.first);
    jsonResponse = jsonDecode(data);
  } catch (e) {
    jsonResponse = <String, Object>{
      'success': false,
      'errorMessage': e.toString(),
    };
  }
  if (client != null) {
    client.destroy();
  }
  return jsonResponse;
}

/// Closes the ServerSocket and removes the [serverInfoFile] that is used
/// to access this instance of the Resident Frontend Server as well as the
/// lock to prevent the concurrent start race.
Future<void> residentServerCleanup(
    ServerSocket server, File serverInfoFile) async {
  final serverFilesystemLock =
      Link('${serverInfoFile.path}$RESIDENT_SERVER_LINK_POSTFIX');
  try {
    if (_cleanupHandler != null) {
      _cleanupHandler.cancel();
    }
    if (serverInfoFile.existsSync()) {
      serverInfoFile.deleteSync();
    }
  } catch (_) {
  } finally {
    try {
      if (serverFilesystemLock.existsSync()) {
        serverFilesystemLock.deleteSync();
      }
    } catch (_) {}
  }

  await server.close();
}

/// Starts a timer that will shut down the resident frontend server in
/// the amount of time specified by [timerDuration], if it is not cancelled.
Timer startShutdownTimer(
    Duration timerDuration, ServerSocket server, File serverInfoFile) {
  return Timer(timerDuration, () async {
    await residentServerCleanup(server, serverInfoFile);
  });
}

/// Listens for compilation commands from socket connections on the
/// provided [address] and [port].
/// If the last request exceeds the amount of time specified by
/// [inactivityTimeout], the server will bring itself down
Future<StreamSubscription<Socket>> residentListenAndCompile(
    InternetAddress address, int port, File serverInfoFile,
    {Duration inactivityTimeout = const Duration(minutes: 30)}) async {
  ServerSocket server;
  // Create a link to the serverInfoFile to ensure that concurrent requests
  // to start the server result in only 1 server being started. This
  // also ensures that the serverInfoFile is only
  // visible once the server is started and ready to receive connections.
  // TODO https://github.com/dart-lang/sdk/issues/49647 use exclusive mode
  // on File objects
  final serverInfoLink =
      Link('${serverInfoFile.path}$RESIDENT_SERVER_LINK_POSTFIX');
  try {
    try {
      serverInfoLink.createSync(serverInfoFile.path);
    } catch (e) {
      // TODO: https://github.com/dart-lang/sdk/issues/49647 Using a File
      // in exclusive mode removes the need for this check.
      if (Platform.isWindows && e.toString().contains('errno = 1314')) {
        throw StateError('Dart must be running in Administrator mode '
            'or Developer mode must be enabled when '
            'using the Resident Frontend Compiler.');
      }
      throw StateError('A server is already running.');
    }
    server = await ServerSocket.bind(address, port);
    serverInfoFile
      ..writeAsStringSync(
          'address:${server.address.address} port:${server.port}');
  } on StateError catch (e) {
    print('Error: $e\n');
    return null;
  } catch (e) {
    // lock was acquired but bind or writing failed
    try {
      serverInfoLink.deleteSync();
    } catch (_) {}
    print('Error: $e\n');
    return null;
  }

  _cleanupHandler = ProcessSignal.sigint.watch().listen((signal) async {
    await residentServerCleanup(server, serverInfoFile);
    exit(1);
  });
  var shutdownTimer =
      startShutdownTimer(inactivityTimeout, server, serverInfoFile);
  print('The Resident Frontend Compiler is listening at '
      '${server.address.address}:${server.port}');

  return server.listen((client) {
    client.listen((Uint8List data) async {
      String result = await ResidentFrontendServer.handleRequest(
          String.fromCharCodes(data));
      client.write(result);
      shutdownTimer.cancel();
      if (result == ResidentFrontendServer._shutdownJsonResponse) {
        await residentServerCleanup(server, serverInfoFile);
      } else {
        shutdownTimer =
            startShutdownTimer(inactivityTimeout, server, serverInfoFile);
      }
    }, onError: (error) {
      client.close();
    }, onDone: () {
      client.close();
    });
  }, onError: (_) async {
    shutdownTimer.cancel();
    await residentServerCleanup(server, serverInfoFile);
  });
}
