// 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 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handler_exit.dart';
import 'package:analysis_server/src/lsp/handlers/handler_reject.dart';
import 'package:analysis_server/src/lsp/handlers/handler_shutdown.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analyzer/dart/analysis/results.dart';

/// Converts an iterable using the provided function and skipping over any
/// null values.
Iterable<T> convert<T, E>(Iterable<E> items, T Function(E) converter) {
  // TODO(dantup): Now this is used outside of handlers, is there somewhere
  // better to put it, and/or a better name for it?
  return items.map(converter).where((item) => item != null);
}

abstract class CommandHandler<P, R> with Handler<P, R> {
  CommandHandler(LspAnalysisServer server) {
    this.server = server;
  }

  Future<ErrorOr<void>> handle(List<dynamic> arguments);
}

mixin Handler<P, R> {
  LspAnalysisServer server;

  ErrorOr<R> error<R>(ErrorCodes code, String message, String data) =>
      new ErrorOr<R>.error(new ResponseError(code, message, data));

  ErrorOr<R> failure<R>(ErrorOr<dynamic> error) =>
      new ErrorOr<R>.error(error.error);

  Future<ErrorOr<ResolvedUnitResult>> requireResolvedUnit(String path) async {
    final result = await server.getResolvedUnit(path);
    if (result?.state != ResultState.VALID) {
      return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
    }
    return success(result);
  }

  ErrorOr<ParsedUnitResult> requireUnresolvedUnit(String path) {
    final result = server.getParsedUnit(path);
    if (result?.state != ResultState.VALID) {
      return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
    }
    return success(result);
  }

  ErrorOr<R> success<R>([R t]) => new ErrorOr<R>.success(t);
}

/// An object that can handle messages and produce responses for requests.
///
/// Clients may not extend, implement or mix-in this class.
abstract class MessageHandler<P, R> with Handler<P, R> {
  MessageHandler(LspAnalysisServer server) {
    this.server = server;
  }

  /// The method that this handler can handle.
  Method get handlesMessage;

  P convertParams(Map<String, dynamic> json);

  FutureOr<ErrorOr<R>> handle(P params);

  /// Handle the given [message]. If the [message] is a [RequestMessage], then the
  /// return value will be sent back in a [ResponseMessage].
  /// [NotificationMessage]s are not expected to return results.
  FutureOr<ErrorOr<R>> handleMessage(IncomingMessage message) {
    final params = convertParams(message.params);
    return handle(params);
  }
}

/// A message handler that handles all messages for a given server state.
abstract class ServerStateMessageHandler {
  final LspAnalysisServer server;
  final Map<Method, MessageHandler> _messageHandlers = {};

  ServerStateMessageHandler(this.server) {
    // All server states support shutdown and exit.
    registerHandler(new ShutdownMessageHandler(server));
    registerHandler(new ExitMessageHandler(server));
  }

  ErrorOr<Object> failure<Object>(ErrorCodes code, String message,
          [String data]) =>
      new ErrorOr<Object>.error(new ResponseError(code, message, data));

  /// Handle the given [message]. If the [message] is a [RequestMessage], then the
  /// return value will be sent back in a [ResponseMessage].
  /// [NotificationMessage]s are not expected to return results.
  FutureOr<ErrorOr<Object>> handleMessage(IncomingMessage message) async {
    final handler = _messageHandlers[message.method];
    return handler != null
        ? handler.handleMessage(message)
        : handleUnknownMessage(message);
  }

  FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
    // If it's an optional *Notification* we can ignore it (return success).
    // Otherwise respond with failure. Optional Requests must still be responded
    // to so they don't leave open requests on the client.
    return _isOptionalNotification(message)
        ? success()
        : failure(
            ErrorCodes.MethodNotFound, 'Unknown method ${message.method}');
  }

  registerHandler(MessageHandler handler) {
    assert(
        handler.handlesMessage != null,
        'Unable to register handler ${handler.runtimeType} because it does '
        'not declare which messages it can handle');

    _messageHandlers[handler.handlesMessage] = handler;
  }

  reject(Method method, ErrorCodes code, String message) {
    registerHandler(new RejectMessageHandler(server, method, code, message));
  }

  ErrorOr<Object> success<Object>([Object t]) => new ErrorOr<Object>.success(t);

  bool _isOptionalNotification(IncomingMessage message) {
    // Not a notification.
    if (message is! NotificationMessage) {
      return false;
    }

    // Messages that start with $/ are optional.
    final stringValue = message.method.toJson();
    return stringValue is String && stringValue.startsWith(r'$/');
  }
}
