// 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 = new 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 = new Stopwatch()..start();

    Completer<int> whenComplete = new 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(new Request('${_nextId++}', 'server.setSubscriptions', {
      'subscriptions': ['STATUS'],
    }));

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

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

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

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

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

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

  @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);
  }

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

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

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