// Copyright (c) 2014, 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.

/// Support for client code that needs to interact with the requests, responses
/// and notifications that are part of the analysis server's wire protocol.
library;

import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart';
import 'package:analyzer/src/utilities/cancellation.dart';

export 'package:analyzer_plugin/protocol/protocol.dart' show Enum;

/// A notification that can be sent from the server about an event that
/// occurred.
///
/// Clients may not extend, implement or mix-in this class.
class Notification {
  /// The name of the JSON attribute containing the name of the event that
  /// triggered the notification.
  static const String eventAttributeName = 'event';

  /// The name of the JSON attribute containing the result values.
  static const String paramsAttributeName = 'params';

  /// The name of the event that triggered the notification.
  final String event;

  /// A table mapping the names of notification parameters to their values, or
  /// `null` if there are no notification parameters.
  final Map<String, Object?>? params;

  /// Initialize a newly created [Notification] to have the given [event] name.
  /// If [params] is provided, it will be used as the params; otherwise no
  /// params will be used.
  Notification(this.event, [this.params]);

  /// Initialize a newly created instance based on the given JSON data.
  factory Notification.fromJson(Map<Object?, Object?> json) {
    return Notification(
      json[Notification.eventAttributeName] as String,
      json[Notification.paramsAttributeName] as Map<String, Object?>?,
    );
  }

  /// Returns a table representing the structure of the JSON object that will be
  /// sent to the client to represent this response.
  Map<String, Object> toJson() => {
    eventAttributeName: event,
    paramsAttributeName: ?params,
  };
}

/// A request that was received from the client.
///
/// Clients may not extend, implement or mix-in this class.
class Request extends RequestOrResponse {
  /// The name of the JSON attribute containing the id of the request.
  static const String idAttributeName = 'id';

  /// The name of the JSON attribute containing the name of the request.
  static const String methodAttributeName = 'method';

  /// The name of the JSON attribute containing the request parameters.
  static const String paramsAttributeName = 'params';

  /// The name of the optional JSON attribute indicating the time (milliseconds
  /// since epoch) at which the client made the request.
  static const String clientRequestTimeAttributeName = 'clientRequestTime';

  /// The unique identifier used to identify this request.
  @override
  final String id;

  /// The method being requested.
  final String method;

  /// A table mapping the names of request parameters to their values.
  final Map<String, Object?> params;

  /// The time (milliseconds since epoch) at which the client made the request
  /// or `null` if this information is not provided by the client.
  final int? clientRequestTime;

  /// Initialize a newly created [Request] to have the given [id] and [method]
  /// name. If [params] is supplied, it is used as the "params" map for the
  /// request. Otherwise an empty "params" map is allocated.
  Request(
    this.id,
    this.method, [
    Map<String, Object?>? params,
    this.clientRequestTime,
  ]) : params = params ?? <String, Object?>{};

  @override
  int get hashCode {
    return id.hashCode;
  }

  /// Returns the amount of time (in milliseconds) since the client sent this
  /// request or `null` if the client did not provide [clientRequestTime].
  int? get timeSinceRequest {
    var clientRequestTime = this.clientRequestTime;
    return clientRequestTime != null
        ? DateTime.now().millisecondsSinceEpoch - clientRequestTime
        : null;
  }

  @override
  bool operator ==(Object other) {
    return other is Request &&
        id == other.id &&
        method == other.method &&
        clientRequestTime == other.clientRequestTime &&
        _equalMaps(params, other.params);
  }

  /// Returns a table representing the structure of the JSON object that will be
  /// sent to the client to represent this response.
  Map<String, Object> toJson() => {
    idAttributeName: id,
    methodAttributeName: method,
    if (params.isNotEmpty) paramsAttributeName: params,
    clientRequestTimeAttributeName: ?clientRequestTime,
  };

  bool _equalLists(List<Object?> first, List<Object?> second) {
    var length = first.length;
    if (length != second.length) {
      return false;
    }
    for (var i = 0; i < length; i++) {
      if (!_equalObjects(first[i], second[i])) {
        return false;
      }
    }
    return true;
  }

  bool _equalMaps(Map<Object?, Object?> first, Map<Object?, Object?> second) {
    if (first.length != second.length) {
      return false;
    }
    for (var key in first.keys) {
      if (!second.containsKey(key)) {
        return false;
      }
      if (!_equalObjects(first[key], second[key])) {
        return false;
      }
    }
    return true;
  }

  bool _equalObjects(Object? first, Object? second) {
    if (first == null) {
      return second == null;
    }
    if (second == null) {
      return false;
    }
    if (first is Map) {
      if (second is Map) {
        return _equalMaps(first, second);
      }
      return false;
    }
    if (first is List) {
      if (second is List) {
        return _equalLists(first, second);
      }
      return false;
    }
    return first == second;
  }

  /// Returns a request parsed from the given JSON [result], or `null` if the
  /// data is not a valid JSON representation of a request. The data is expected
  /// to have the following format:
  ///
  ///     {
  ///       'clientRequestTime': millisecondsSinceEpoch
  ///       'id': String,
  ///       'method': methodName,
  ///       'params': {
  ///         parameter_name: value
  ///       }
  ///     }
  ///
  /// where both the parameters and `clientRequestTime` are optional.
  ///
  /// The parameters can contain any number of name/value pairs. The
  /// `clientRequestTime` must be an int representing the time at which the
  /// client issued the request (milliseconds since epoch).
  static Request? fromJson(Map<String, Object?> result) {
    var id = result[Request.idAttributeName];
    var method = result[Request.methodAttributeName];
    if (id is! String || method is! String) {
      return null;
    }
    var time = result[Request.clientRequestTimeAttributeName];
    if (time is! int?) {
      return null;
    }
    var params = result[Request.paramsAttributeName];
    if (params is Map<String, Object?>?) {
      return Request(id, method, params, time);
    } else {
      return null;
    }
  }
}

/// An exception that occurred during the handling of a request that requires
/// that an error be returned to the client.
///
/// Clients may not extend, implement or mix-in this class.
class RequestFailure implements Exception {
  /// The response to be returned as a result of the failure.
  final Response response;

  /// Initialize a newly created exception to return the given response.
  RequestFailure(this.response);
}

/// An object that can handle requests and produce responses for them.
///
/// Clients may not extend, implement or mix-in this class.
abstract class RequestHandler {
  /// Attempt to handle the given [request]. If the request is not recognized by
  /// this handler, return `null` so that other handlers will be given a chance
  /// to handle it. Otherwise, return the response that should be passed back to
  /// the client.
  Response? handleRequest(Request request, CancellationToken cancellationToken);
}

/// A request or response that was received from the client.
///
/// Clients may not extend, implement or mix-in this class.
abstract class RequestOrResponse {
  /// The unique identifier associated with this request or response.
  String get id;
}

/// A response to a request.
///
/// Clients may not extend, implement or mix-in this class.
class Response extends RequestOrResponse {
  /// The name of the JSON attribute containing the id of the request for which
  /// this is a response.
  static const String idAttributeName = 'id';

  /// The name of the JSON attribute containing the error message.
  static const String errorAttributeName = 'error';

  /// The name of the JSON attribute containing the result values.
  static const String resultAttributeName = 'result';

  /// The unique identifier used to identify the request that this response is
  /// associated with.
  @override
  final String id;

  /// The error that was caused by attempting to handle the request, or `null`
  /// if there was no error.
  final RequestError? error;

  /// A table mapping the names of result fields to their values.  Should be
  /// `null` if there is no result to send.
  Map<String, Object?>? result;

  /// Initialize a newly created instance to represent a response to a request
  /// with the given [id].  If [result] is provided, it will be used as the
  /// result; otherwise an empty result will be used.  If an [error] is provided
  /// then the response will represent an error condition.
  Response(this.id, {this.result, this.error});

  /// Initialize a newly created instance to represent the CONTENT_MODIFIED
  /// error condition.
  Response.contentModified(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.CONTENT_MODIFIED,
          'File was modified before the operation completed.',
        ),
      );

  /// Create and return the `DEBUG_PORT_COULD_NOT_BE_OPENED` error response.
  Response.debugPortCouldNotBeOpened(Request request, Object? error)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.DEBUG_PORT_COULD_NOT_BE_OPENED,
          '$error',
        ),
      );

  /// Initialize a newly created instance to represent the FILE_NOT_ANALYZED
  /// error condition.
  Response.fileNotAnalyzed(Request request, String file)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.FILE_NOT_ANALYZED,
          'File is not analyzed: $file.',
        ),
      );

  /// Initialize a newly created instance to represent the FORMAT_INVALID_FILE
  /// error condition.
  Response.formatInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.FORMAT_INVALID_FILE,
          'Error during `${request.method}`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent the FORMAT_WITH_ERROR
  /// error condition.
  Response.formatWithErrors(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.FORMAT_WITH_ERRORS,
          'Error during `edit.format`: source contains syntax errors.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// GET_ERRORS_INVALID_FILE error condition.
  Response.getErrorsInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.GET_ERRORS_INVALID_FILE,
          'Error during `analysis.getErrors`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// GET_FIXES_INVALID_FILE error condition.
  Response.getFixesInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.GET_FIXES_INVALID_FILE,
          'Error during `edit.getFixes`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// GET_IMPORTED_ELEMENTS_INVALID_FILE error condition.
  Response.getImportedElementsInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.GET_IMPORTED_ELEMENTS_INVALID_FILE,
          'Error during `analysis.getImportedElements`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// GET_NAVIGATION_INVALID_FILE error condition.
  Response.getNavigationInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.GET_NAVIGATION_INVALID_FILE,
          'Error during `analysis.getNavigation`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// GET_REACHABLE_SOURCES_INVALID_FILE error condition.
  Response.getReachableSourcesInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.GET_REACHABLE_SOURCES_INVALID_FILE,
          'Error during `analysis.getReachableSources`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// GET_SIGNATURE_INVALID_FILE error condition.
  Response.getSignatureInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.GET_SIGNATURE_INVALID_FILE,
          'Error during `analysis.getSignature`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// GET_SIGNATURE_INVALID_OFFSET error condition.
  Response.getSignatureInvalidOffset(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.GET_SIGNATURE_INVALID_OFFSET,
          'Error during `analysis.getSignature`: invalid offset.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// GET_SIGNATURE_UNKNOWN_FUNCTION error condition.
  Response.getSignatureUnknownFunction(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.GET_SIGNATURE_UNKNOWN_FUNCTION,
          'Error during `analysis.getSignature`: unknown function.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// IMPORT_ELEMENTS_INVALID_FILE error condition.
  Response.importElementsInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.IMPORT_ELEMENTS_INVALID_FILE,
          'Error during `edit.importElements`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent an error condition caused
  /// by an analysis.reanalyze [request] that specifies an analysis root that is
  /// not in the current list of analysis roots.
  Response.invalidAnalysisRoot(Request request, String rootPath)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.INVALID_ANALYSIS_ROOT,
          'Invalid analysis root: $rootPath',
        ),
      );

  /// Initialize a newly created instance to represent an error condition caused
  /// by a [request] that specifies an execution context whose context root does
  /// not exist.
  Response.invalidExecutionContext(Request request, String contextId)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.INVALID_EXECUTION_CONTEXT,
          'Invalid execution context: $contextId',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// INVALID_FILE_PATH_FORMAT error condition.
  Response.invalidFilePathFormat(Request request, Object? path)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.INVALID_FILE_PATH_FORMAT,
          'Invalid file path format: $path',
        ),
      );

  /// Initialize a newly created instance to represent an error condition caused
  /// by a [request] that had invalid parameter.  [path] is the path to the
  /// invalid parameter, in JavaScript notation (e.g. "foo.bar" means that the
  /// parameter "foo" contained a key "bar" whose value was the wrong type).
  /// [expectation] is a description of the type of data that was expected.
  Response.invalidParameter(Request request, String path, String expectation)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.INVALID_PARAMETER,
          "Invalid parameter '$path'. $expectation.",
        ),
      );

  /// Initialize a newly created instance to represent an error condition caused
  /// by a malformed request.
  Response.invalidRequestFormat()
    : this(
        '',
        error: RequestError(
          RequestErrorCode.INVALID_REQUEST,
          'Invalid request',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// ORGANIZE_DIRECTIVES_ERROR error condition.
  Response.organizeDirectivesError(Request request, String message)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.ORGANIZE_DIRECTIVES_ERROR,
          message,
        ),
      );

  /// Initialize a newly created instance to represent the
  /// REFACTORING_REQUEST_CANCELLED error condition.
  Response.refactoringRequestCancelled(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.REFACTORING_REQUEST_CANCELLED,
          'The `edit.getRefactoring` request was cancelled.',
        ),
      );

  /// Initialize a newly created instance to represent the SERVER_ERROR error
  /// condition.
  factory Response.serverError(
    Request request,
    Object? exception,
    Object? stackTrace,
  ) {
    var error = RequestError(
      RequestErrorCode.SERVER_ERROR,
      exception.toString(),
    );
    if (stackTrace != null) {
      error.stackTrace = stackTrace.toString();
    }
    return Response(request.id, error: error);
  }

  /// Initialize a newly created instance to represent the
  /// SORT_MEMBERS_INVALID_FILE error condition.
  Response.sortMembersInvalidFile(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.SORT_MEMBERS_INVALID_FILE,
          'Error during `edit.sortMembers`: invalid file.',
        ),
      );

  /// Initialize a newly created instance to represent the
  /// SORT_MEMBERS_PARSE_ERRORS error condition.
  Response.sortMembersParseErrors(Request request, int numErrors)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.SORT_MEMBERS_PARSE_ERRORS,
          'Error during `edit.sortMembers`: file has $numErrors scan/parse errors.',
        ),
      );

  /// Initialize a newly created instance to represent an error condition caused
  /// by a [request] that cannot be handled by any known handlers.
  Response.unknownRequest(Request request)
    : this(
        request.id,
        error: RequestError(
          RequestErrorCode.UNKNOWN_REQUEST,
          'Unknown request',
        ),
      );

  /// Initialize a newly created instance to represent an error condition caused
  /// by a [request] for a service that is not supported.
  Response.unsupportedFeature(String requestId, String message)
    : this(
        requestId,
        error: RequestError(RequestErrorCode.UNSUPPORTED_FEATURE, message),
      );

  /// Return a table representing the structure of the Json object that will be
  /// sent to the client to represent this response.
  Map<String, Object> toJson() => {
    idAttributeName: id,
    errorAttributeName: ?error?.toJson(clientUriConverter: null),
    resultAttributeName: ?result,
  };

  /// Initialize a newly created instance based on the given JSON data.
  static Response? fromJson(Map<String, Object?> json) {
    try {
      var id = json[Response.idAttributeName];
      if (id is! String) {
        return null;
      }

      RequestError? decodedError;
      var error = json[Response.errorAttributeName];
      if (error is Map) {
        decodedError = RequestError.fromJson(
          ResponseDecoder(null),
          '.error',
          error,
          clientUriConverter: null,
        );
      }

      Map<String, Object?>? decodedResult;
      var result = json[Response.resultAttributeName];
      if (result is Map<String, Object?>) {
        decodedResult = result;
      }

      return Response(id, error: decodedError, result: decodedResult);
    } catch (exception) {
      return null;
    }
  }
}
