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

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:analysis_server/src/server/driver.dart' show Driver;
import 'package:analysis_server_client/protocol.dart'
    show
        AddContentOverlay,
        AnalysisUpdateContentParams,
        EditBulkFixesResult,
        ResponseDecoder;
import 'package:args/args.dart';
import 'package:path/path.dart' as path;

import 'core.dart';
import 'experiments.dart';
import 'sdk.dart';
import 'utils.dart';

/// When set, this function is executed just before the Analysis Server starts.
void Function(String cmdName, List<FileSystemEntity> analysisRoots,
    ArgResults? argResults)? preAnalysisServerStart;

/// A class to provide an API wrapper around an analysis server process.
class AnalysisServer {
  AnalysisServer(
    this.packagesFile,
    this.sdkPath,
    this.analysisRoots, {
    this.cacheDirectoryPath,
    required this.commandName,
    required this.argResults,
    this.enabledExperiments = const [],
    this.disableStatusNotificationDebouncing = false,
    this.suppressAnalytics = false,
    bool useAotSnapshot = false,
  }) : _useAotSnapshot = useAotSnapshot;

  final String? cacheDirectoryPath;
  final File? packagesFile;
  final Directory sdkPath;
  final List<FileSystemEntity> analysisRoots;
  final String commandName;
  final ArgResults? argResults;
  final List<String> enabledExperiments;
  final bool disableStatusNotificationDebouncing;
  final bool suppressAnalytics;
  final bool _useAotSnapshot;

  Process? _process;

  /// When not null, this is a [Completer] which completes when analysis has
  /// finished, otherwise `null`.
  Completer<bool>? _analysisFinished;

  int _id = 0;

  bool _shutdownResponseReceived = false;

  bool _serverErrorReceived = false;

  /// Whether any server error occurred that could mean analysis was not
  /// performed correctly.
  bool get serverErrorReceived => _serverErrorReceived;

  Stream<bool> get onAnalyzing {
    // {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}}
    return _streamController('server.status')
        .stream
        .where((event) => event['analysis'] != null)
        .map((event) => (event['analysis']['isAnalyzing']!) as bool);
  }

  /// This future completes when we next receive an analysis finished event
  /// (unless there's no current analysis and we've already received a complete
  /// event, in which case this future completes immediately).
  Future<bool>? get analysisFinished => _analysisFinished?.future;

  Stream<FileAnalysisErrors> get onErrors {
    // {"event":"analysis.errors",
    //  "params":{"file":"/Users/.../lib/main.dart","errors":[]}}
    return _streamController('analysis.errors').stream.map((event) {
      final file = event['file'] as String;
      final errorsList = event['errors'] as List<dynamic>;
      final errors = [
        for (final error in errorsList)
          AnalysisError((error as Map).cast<String, dynamic>())
      ];
      return FileAnalysisErrors(file, errors);
    });
  }

  Future<int> get onExit => _process!.exitCode;

  final Map<String, StreamController<Map<String, dynamic>>> _streamControllers =
      {};

  /// Completes when an analysis server crash has been detected.
  Future<void> get onCrash => _onCrash.future;

  final _onCrash = Completer<void>();

  final Map<String, Completer<Map<String, dynamic>>> _requestCompleters = {};

  /// Starts the process and returns the pid for it.
  Future<int> start({bool setAnalysisRoots = true}) async {
    preAnalysisServerStart?.call(commandName, analysisRoots, argResults);

    final process = await _startProcess();
    _process = process;
    _shutdownResponseReceived = false;
    // This callback hookup can't throw.
    process.exitCode.whenComplete(() {
      _process = null;

      if (!_shutdownResponseReceived) {
        // The process exited unexpectedly. Report the crash.
        // If `server.error` reported an error, that has been logged by
        // `_handleServerError`.

        final error = StateError('The analysis server crashed unexpectedly');

        final analysisFinished = _analysisFinished;
        if (analysisFinished != null && !analysisFinished.isCompleted) {
          // Complete this completer in order to unstick the process.
          analysisFinished.completeError(error);
        }

        // Complete these completers in order to unstick the process.
        for (final completer in _requestCompleters.values) {
          completer.completeError(error);
        }

        _onCrash.complete();
      }
    });

    final errorStream = process.stderr
        .transform<String>(utf8.decoder)
        .transform<String>(const LineSplitter());
    errorStream.listen(log.stderr);

    final inStream = process.stdout
        .transform<String>(utf8.decoder)
        .transform<String>(const LineSplitter());
    inStream.listen(_handleServerResponse);

    _streamController('server.error').stream.listen(_handleServerError);

    _streamController('server.pluginError').stream.listen(_handlePluginError);

    _sendCommand('server.setSubscriptions', params: <String, dynamic>{
      'subscriptions': <String>['STATUS'],
    });

    // Reference and trim off any trailing slash, the Dart Analysis Server
    // protocol throws an error (INVALID_FILE_PATH_FORMAT) if there is a
    // trailing slash.
    //
    // The call to `absolute.resolveSymbolicLinksSync()` canonicalizes the path
    // to be passed to the analysis server.
    final analysisRootPaths = [
      for (final root in analysisRoots)
        trimEnd(
            root.absolute.resolveSymbolicLinksSync(), path.context.separator),
    ];

    onAnalyzing.listen((isAnalyzing) {
      final analysisFinished = _analysisFinished;
      if (isAnalyzing && (analysisFinished?.isCompleted ?? true)) {
        // Start a new completer, to be completed when we receive the
        // corresponding analysis complete event.
        _analysisFinished = Completer();
      } else if (!isAnalyzing &&
          analysisFinished != null &&
          !analysisFinished.isCompleted) {
        analysisFinished.complete(true);
      }
    });

    if (setAnalysisRoots) {
      await _sendCommand('analysis.setAnalysisRoots', params: {
        'included': analysisRootPaths,
        'excluded': [],
      });
    }

    return process.pid;
  }

  Future<Process> _startProcess() {
    final executable = _useAotSnapshot ? sdk.dartAotRuntime : sdk.dart;
    final arguments = [
      if (_useAotSnapshot)
        sdk.analysisServerAotSnapshot
      else
        sdk.analysisServerSnapshot,
      if (suppressAnalytics) '--${Driver.SUPPRESS_ANALYTICS_FLAG}',
      '--${Driver.CLIENT_ID}=dart-$commandName',
      '--disable-server-feature-completion',
      '--disable-server-feature-search',
      if (disableStatusNotificationDebouncing)
        '--disable-status-notification-debouncing',
      '--disable-silent-analysis-exceptions',
      '--sdk',
      sdkPath.path,
      if (cacheDirectoryPath != null) '--cache=$cacheDirectoryPath',
      if (packagesFile != null) '--packages=${packagesFile!.path}',
      if (enabledExperiments.isNotEmpty)
        '--$experimentFlagName=${enabledExperiments.join(',')}',
    ];

    log.trace('$executable ${arguments.join(' ')}');
    return Process.start(executable, arguments);
  }

  Future<String> getVersion() {
    return _sendCommand('server.getVersion')
        .then((response) => response['version']);
  }

  Future<EditBulkFixesResult> requestBulkFixes(
      String filePath, bool inTestMode, List<String> codes,
      {bool updatePubspec = false}) {
    return _sendCommand('edit.bulkFixes', params: <String, dynamic>{
      'included': [path.canonicalize(filePath)],
      'inTestMode': inTestMode,
      'updatePubspec': updatePubspec,
      if (codes.isNotEmpty) 'codes': codes,
    }).then((result) {
      return EditBulkFixesResult.fromJson(
          ResponseDecoder(null), 'result', result);
    });
  }

  Future<void> shutdown({Duration? timeout}) async {
    // Request shutdown.
    final Future<void> future =
        _sendCommand('server.shutdown').then((Map<String, dynamic> value) {
      _shutdownResponseReceived = true;
      return;
    });
    await (timeout != null
            ? future.timeout(timeout, onTimeout: () {
                log.stderr(
                    'The analysis server timed out while shutting down.');
              })
            : future)
        .whenComplete(dispose);
  }

  /// Send an `analysis.updateContent` request with the given [files].
  Future<void> updateContent(Map<String, AddContentOverlay> files) async {
    await _sendCommand('analysis.updateContent',
        params: AnalysisUpdateContentParams(files).toJson());
  }

  Future<Map<String, dynamic>> _sendCommand(String method,
      {Map<String, dynamic>? params}) {
    final String id = (++_id).toString();
    final String message = json.encode(<String, dynamic>{
      'id': id,
      'method': method,
      'params': params,
    });

    final Completer<Map<String, dynamic>> completer = Completer();

    _requestCompleters[id] = completer;
    _process!.stdin.writeln(message);

    log.trace('==> $message');

    return completer.future;
  }

  void _handlePluginError(Map<String, dynamic>? error) {
    _serverErrorReceived = true;
    final err = error!;
    // No need for a preamble (like in _handleServerError); the message should
    // have all of the context necessary.
    log.stderr(err['message']);
    final stackTrace = err['stackTrace'];
    if (stackTrace is String && stackTrace.isNotEmpty) {
      log.stderr(stackTrace);
    }
  }

  void _handleServerResponse(String line) {
    log.trace('<== $line');

    final response = json.decode(line) as Object?;

    if (response is Map<String, dynamic>) {
      if (response
          case {'event': final String event, 'params': final Object? params}) {
        if (params is Map<String, dynamic>) {
          _streamController(event).add(params.cast<String, dynamic>());
        }
      } else if (response case {'id': final String id}) {
        if (response case {'error': final Map<String, Object?> error}) {
          _requestCompleters.remove(id)?.completeError(
              RequestError.parse(error.cast<String, dynamic>()));
        } else {
          _requestCompleters.remove(id)?.complete(response['result'] ?? {});
        }
      }
    }
  }

  void _handleServerError(Map<String, dynamic>? error) {
    _serverErrorReceived = true;
    final err = error!;
    log.stderr('An unexpected error was encountered by the Analysis Server.');
    log.stderr('Please file an issue at '
        'https://github.com/dart-lang/sdk/issues/new/choose with the following '
        'details:\n');
    // Fields are 'isFatal', 'message', and 'stackTrace'.
    log.stderr(err['message']);
    final stackTrace = err['stackTrace'];
    if (stackTrace is String && stackTrace.isNotEmpty) {
      log.stderr(stackTrace);
    }
  }

  StreamController<Map<String, dynamic>> _streamController(String streamId) {
    return _streamControllers.putIfAbsent(
        streamId, () => StreamController<Map<String, dynamic>>.broadcast());
  }

  Future<bool> dispose() async {
    return _process?.kill() ?? true;
  }
}

enum _AnalysisSeverity {
  error,
  warning,
  info,
  none,
}

class AnalysisError implements Comparable<AnalysisError> {
  AnalysisError(this.json);

  static final Map<String, _AnalysisSeverity> _severityMap =
      <String, _AnalysisSeverity>{
    'INFO': _AnalysisSeverity.info,
    'WARNING': _AnalysisSeverity.warning,
    'ERROR': _AnalysisSeverity.error,
  };

  // "severity":"INFO","type":"TODO","location":{
  //   "file":"/Users/.../lib/test.dart","offset":362,"length":72,"startLine":15,"startColumn":4
  // },"message":"...","hasFix":false}
  Map<String, dynamic> json;

  String? get severity => json['severity'] as String?;

  _AnalysisSeverity get _severityLevel =>
      _severityMap[severity!] ?? _AnalysisSeverity.none;

  bool get isInfo => _severityLevel == _AnalysisSeverity.info;

  bool get isWarning => _severityLevel == _AnalysisSeverity.warning;

  bool get isError => _severityLevel == _AnalysisSeverity.error;

  String get type => json['type'] as String;

  String get message => json['message'] as String;

  String get code => json['code'] as String;

  String? get correction => json['correction'] as String?;

  int? get endColumn => json['location']['endColumn'] as int?;

  int? get endLine => json['location']['endLine'] as int?;

  String get file => json['location']['file'] as String;

  int? get startLine => json['location']['startLine'] as int?;

  int? get startColumn => json['location']['startColumn'] as int?;

  int get offset => json['location']['offset'] as int;

  int get length => json['location']['length'] as int;

  String? get url => json['url'] as String?;

  List<DiagnosticMessage> get contextMessages {
    var messages = json['contextMessages'] as List<dynamic>?;
    if (messages == null) {
      // The field is optional, so we return an empty list as a default value.
      return [];
    }
    return messages.map((message) => DiagnosticMessage(message)).toList();
  }

  @override
  int compareTo(AnalysisError other) {
    // Sort in order of severity, file path, error location, and message.
    final int diff = _severityLevel.index - other._severityLevel.index;
    if (diff != 0) {
      return diff;
    }

    if (file != other.file) {
      return file.compareTo(other.file);
    }

    if (offset != other.offset) {
      return offset - other.offset;
    }

    return message.compareTo(other.message);
  }

  @override
  String toString() => '${severity!.toLowerCase()} • '
      '$message • $file:$startLine:$startColumn • '
      '($code)';
}

class DiagnosticMessage {
  final Map<String, dynamic> json;

  DiagnosticMessage(this.json);

  int? get column => json['location']['startColumn'] as int?;

  int? get endColumn => json['location']['endColumn'] as int?;

  int? get endLine => json['location']['endLine'] as int?;

  String get filePath => json['location']['file'] as String;

  int get length => json['location']['length'] as int;

  int get line => json['location']['startLine'] as int;

  String get message => json['message'] as String;

  int get offset => json['location']['offset'] as int;
}

class FileAnalysisErrors {
  final String file;
  final List<AnalysisError> errors;

  FileAnalysisErrors(this.file, this.errors);
}

class RequestError {
  static RequestError parse(dynamic error) {
    return RequestError(
      error['code'],
      error['message'],
      stackTrace: error['stackTrace'],
    );
  }

  final String code;
  final String message;
  final String stackTrace;

  RequestError(this.code, this.message, {required this.stackTrace});

  @override
  String toString() => '[RequestError code: $code, message: $message]';
}
