// 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 {
  final StreamController<Request> _requestController =
      new StreamController.broadcast();

  final StreamController<Notification> _notificationController =
      new 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 = new 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);
  }
}
