// Copyright (c) 2018, 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:io';

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/socket_server.dart';
import 'package:path/path.dart' as path;

/// Instances of the class [DevAnalysisServer] implement a simple analysis
/// server implementation, used to analyze one or more packages and then
/// terminate the server.
class DevAnalysisServer {
  static bool get _terminalSupportsAnsi {
    return stdout.supportsAnsiEscapes &&
        stdioType(stdout) == StdioType.terminal;
  }

  /// An object that can handle either a WebSocket connection or a connection
  /// to the client over stdio.
  final SocketServer socketServer;

  int _nextId = 0;
  DevChannel _channel;

  /// Initialize a newly created stdio server.
  DevAnalysisServer(this.socketServer);

  void initServer() {
    _channel = DevChannel();
    socketServer.createAnalysisServer(_channel);
  }

  /// Analyze the given directories and display any results to stdout.
  ///
  /// Return a future that will be completed with an exit code when analysis
  /// finishes.
  Future<int> processDirectories(List<String> directories) async {
    final String bold = _terminalSupportsAnsi ? '\u001b[1m' : '';
    final String none = _terminalSupportsAnsi ? '\u001b[0m' : '';

    print('Analyzing ${directories.join(', ')}...');

    Stopwatch timer = Stopwatch()..start();

    Completer<int> whenComplete = Completer();

    int exitCode = 0;

    void handleStatusNotification(Notification notification) {
      Map<String, dynamic> params = notification.params;
      if (params.containsKey('analysis')) {
        bool isAnalyzing = params['analysis']['isAnalyzing'];
        if (!isAnalyzing) {
          timer.stop();
          double seconds = timer.elapsedMilliseconds / 1000.0;
          print('Completed in ${seconds.toStringAsFixed(1)}s.');
          whenComplete.complete(exitCode);
        }
      }
    }

    void handleErrorsNotification(Notification notification) {
      String filePath = notification.params['file'];
      List<Map> errors = notification.params['errors'];

      if (errors.isEmpty) {
        return;
      }

      filePath = path.relative(filePath);

      for (Map error in errors) {
        if (error['type'] == 'TODO') {
          continue;
        }

        String severity = error['severity'].toLowerCase();
        if (severity == 'warning' && exitCode < 1) {
          exitCode = 1;
        } else if (severity == 'error' && exitCode < 2) {
          exitCode = 2;
        }

        String message = error['message'];
        if (message.endsWith('.')) {
          message = message.substring(0, message.length - 1);
        }
        String code = error['code'];
        int line = error['location']['startLine'];
        int column = error['location']['startColumn'];

        print('  $severity • $bold$message$none at $filePath:$line:$column • '
            '($code)');
      }
    }

    void handleServerError(Notification notification) {
      Map<String, dynamic> params = notification.params;
      String message = params['message'];
      String stackTrace = params['stackTrace'];

      print(message);
      if (stackTrace != null) {
        print(stackTrace);
      }

      exitCode = 3;

      // Ensure we terminate training if we get an exception from the analysis
      // server.
      whenComplete.completeError(message);
    }

    StreamSubscription<Notification> notificationSubscriptions =
        _channel.onNotification.listen((Notification notification) {
      if (notification.event == 'server.status') {
        handleStatusNotification(notification);
      } else if (notification.event == 'analysis.errors') {
        handleErrorsNotification(notification);
      } else if (notification.event == 'server.error') {
        handleServerError(notification);
      }
    });

    _channel.sendRequest(Request('${_nextId++}', 'server.setSubscriptions', {
      'subscriptions': ['STATUS'],
    }));

    directories =
        directories.map((dir) => path.normalize(path.absolute(dir))).toList();

    _channel.sendRequest(Request(
      '${_nextId++}',
      'analysis.setAnalysisRoots',
      {'included': directories, 'excluded': []},
    ));

    return whenComplete.future.whenComplete(() {
      notificationSubscriptions.cancel();

      _channel.sendRequest(Request(
        '${_nextId++}',
        'analysis.setAnalysisRoots',
        {'included': [], 'excluded': []},
      ));
    });
  }
}

class DevChannel implements ServerCommunicationChannel {
  final StreamController<Request> _requestController =
      StreamController.broadcast();

  final StreamController<Notification> _notificationController =
      StreamController.broadcast();

  final Map<String, Completer<Response>> _responseCompleters = {};

  Stream<Notification> get onNotification => _notificationController.stream;

  @override
  void close() {
    _notificationController.close();
  }

  @override
  void listen(
    void Function(Request request) onRequest, {
    Function onError,
    void Function() onDone,
  }) {
    _requestController.stream.listen(
      onRequest,
      onError: onError,
      onDone: onDone,
    );
  }

  @override
  void sendNotification(Notification notification) {
    _notificationController.add(notification);
  }

  Future<Response> sendRequest(Request request) {
    Completer<Response> completer = Completer();
    _responseCompleters[request.id] = completer;
    _requestController.add(request);
    return completer.future;
  }

  @override
  void sendResponse(Response response) {
    Completer<Response> completer = _responseCompleters.remove(response.id);
    completer?.complete(response);
  }
}
