// 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,
  });

  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;

  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 = errorsList
          .map<Map<String, dynamic>>(castStringKeyedMap)
          .map<AnalysisError>(
              (Map<String, dynamic> json) => AnalysisError(json))
          .toList();
      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 command = [
      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(',')}'
    ];

    final process = await startDartProcess(sdk, command);
    _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);

    _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<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 _handleServerResponse(String line) {
    log.trace('<== $line');

    final dynamic response = json.decode(line);

    if (response is Map<String, dynamic>) {
      if (response['event'] != null) {
        final event = response['event'] as String;
        final dynamic params = response['params'];

        if (params is Map<String, dynamic>) {
          _streamController(event).add(castStringKeyedMap(params));
        }
      } else if (response['id'] != null) {
        final id = response['id'];

        if (response['error'] != null) {
          final error = castStringKeyedMap(response['error']);
          _requestCompleters
              .remove(id)
              ?.completeError(RequestError.parse(error));
        } 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']);
    if (err['stackTrace'] != null) {
      log.stderr(err['stackTrace'] as String);
    }
  }

  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]';
}
