// Copyright (c) 2017, 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 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart';

/// An interface for enumerated types in the protocol.
///
/// Clients may not extend, implement or mix-in this class.
abstract class Enum {
  /// The name of the enumerated value. This should match the name of the static
  /// getter which provides access to this enumerated value.
  String get name;
}

/// A notification that can be sent to 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 EVENT = 'event';

  /// The name of the JSON attribute containing the result values.
  static const String PARAMS = '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 json) {
    return Notification(json[Notification.EVENT] as String,
        json[Notification.PARAMS] as Map<String, Object>);
  }

  /// 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() {
    var jsonObject = <String, Object>{};
    jsonObject[EVENT] = event;
    final params = this.params;
    if (params != null) {
      jsonObject[PARAMS] = params;
    }
    return jsonObject;
  }
}

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

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

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

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

  /// The unique identifier used to identify this request.
  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 server made the request,
  /// or `null` if this information is not provided by the server.
  final int? serverRequestTime;

  /// 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.serverRequestTime])
      : params = params ?? <String, Object?>{};

  /// Return a request parsed from the given json, 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': {
  ///       paramter_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).
  factory Request.fromJson(Map<String, Object?> result) {
    var id = result[Request.ID];
    var method = result[Request.METHOD];
    if (id is! String || method is! String) {
      throw StateError('Unexpected type for id or method');
    }
    var time = result[Request.SERVER_REQUEST_TIME];
    if (time is! int?) {
      throw StateError('Unexpected type for server request time');
    }
    var params = result[Request.PARAMS];
    if (params is Map<String, Object?>?) {
      return Request(id, method, params, time);
    } else {
      throw StateError('Unexpected type for params');
    }
  }

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

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

  /// Return a table representing the structure of the Json object that will be
  /// sent to the server to represent this response.
  Map<String, Object> toJson() {
    var jsonObject = <String, Object>{};
    jsonObject[ID] = id;
    jsonObject[METHOD] = method;
    if (params.isNotEmpty) {
      jsonObject[PARAMS] = params;
    }
    final serverRequestTime = this.serverRequestTime;
    if (serverRequestTime != null) {
      jsonObject[SERVER_REQUEST_TIME] = serverRequestTime;
    }
    return jsonObject;
  }

  bool _equalLists(List? first, List? second) {
    if (first == null) {
      return second == null;
    }
    if (second == null) {
      return false;
    }
    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? first, Map? second) {
    if (first == null) {
      return second == null;
    }
    if (second == null) {
      return false;
    }
    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;
  }
}

/// A collection of utility methods that create instances of the generated class
/// [RequestError].
///
/// Clients may not extend, implement or mix-in this class.
class RequestErrorFactory {
  /// Return a request error representing an error condition caused by a
  /// [request] that had an invalid edit object.
  static RequestError invalidOverlayChangeInvalidEdit() => RequestError(
      RequestErrorCode.INVALID_OVERLAY_CHANGE,
      'Invalid overlay change: invalid edit');

  /// Return a request error representing an error condition caused by a
  /// [request] that attempted to change an existing overlay when no overlay
  /// existed.
  static RequestError invalidOverlayChangeNoContent() => RequestError(
      RequestErrorCode.INVALID_OVERLAY_CHANGE,
      'Invalid overlay change: no content to change');

  /// Return a request error representing an error condition caused by a request
  /// that had an invalid parameter. The [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). The
  /// [expectation] is a description of the type of data that was expected.
  static RequestError invalidParameter(String path, String expectation) =>
      RequestError(RequestErrorCode.INVALID_PARAMETER,
          "Invalid parameter '$path'. $expectation.");

  /// Return a request error representing an error that occurred in the plugin.
  static RequestError pluginError(dynamic exception, String? stackTrace) =>
      RequestError(RequestErrorCode.PLUGIN_ERROR, exception.toString(),
          stackTrace: stackTrace);

  /// Return a request error representing an error condition caused by a request
  /// with the given [method] that cannot be handled by any known handlers.
  static RequestError unknownRequest(String method) => RequestError(
      RequestErrorCode.UNKNOWN_REQUEST, 'Unknown request: $method');
}

/// An exception that occurred during the handling of a request that requires
/// that an error be returned to the server.
///
/// Clients may not extend, implement or mix-in this class.
class RequestFailure implements Exception {
  /// A description of the error that was encountered.
  final RequestError error;

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

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

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

  /// The name of the JSON attribute containing the time at which the request was
  /// handled by the plugin.
  static const String REQUEST_TIME = 'requestTime';

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

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

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

  /// The time at which the request was handled by the plugin.
  final int requestTime;

  /// 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.requestTime, {this.error, this.result});

  /// Initialize a newly created instance based on the given JSON data.
  factory Response.fromJson(Map<String, Object?> json) {
    var id = json[ID];
    if (id is! String) {
      throw StateError('Unexpected type for id');
    }

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

    var requestTime = json[REQUEST_TIME];
    if (requestTime is! int) {
      throw StateError('Unexpected type for requestTime');
    }

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

    return Response(id, requestTime,
        error: decodedError, result: decodedResult);
  }

  /// 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() {
    var jsonObject = <String, Object>{};
    jsonObject[ID] = id;
    final error = this.error;
    if (error != null) {
      jsonObject[ERROR] = error.toJson();
    }
    jsonObject[REQUEST_TIME] = requestTime;
    final result = this.result;
    if (result != null) {
      jsonObject[RESULT] = result;
    }
    return jsonObject;
  }
}
