// 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.

library protocol;

import 'dart:collection';
import 'dart:convert' show JsonDecoder;

import 'package:analysis_services/json.dart';

/**
 * An abstract enumeration.
 */
abstract class Enum2<E extends Enum2> implements Comparable<E> {
  /**
   * The name of this enum constant, as declared in the enum declaration.
   */
  final String name;

  /**
   * The position in the enum declaration.
   */
  final int ordinal;

  const Enum2(this.name, this.ordinal);

  @override
  int get hashCode => ordinal;

  @override
  String toString() => name;

  int compareTo(E other) => ordinal - other.ordinal;

  /**
   * Returns the enum constant with the given [name], `null` if not found.
   */
  static Enum2 valueOf(List<Enum2> values, String name) {
    for (int i = 0; i < values.length; i++) {
      Enum2 value = values[i];
      if (value.name == name) {
        return value;
      }
    }
    return null;
  }
}


/**
 * Instances of the class [Request] represent a request that was received.
 */
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 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 = new HashMap<String, Object>();

  /**
   * A decoder that can be used to decode strings into JSON objects.
   */
  static const JsonDecoder DECODER = const JsonDecoder(null);

  /**
   * Initialize a newly created [Request] to have the given [id] and [method]
   * name.
   */
  Request(this.id, this.method);

  /**
   * Return a request parsed from the given [data], or `null` if the [data] is
   * not a valid json representation of a request. The [data] is expected to
   * have the following format:
   *
   *   {
   *     'id': String,
   *     'method': methodName,
   *     'params': {
   *       paramter_name: value
   *     }
   *   }
   *
   * where the parameters are optional and can contain any number of name/value
   * pairs.
   */
  factory Request.fromString(String data) {
    try {
      var result = DECODER.convert(data);
      if (result is! Map) {
        return null;
      }
      var id = result[Request.ID];
      var method = result[Request.METHOD];
      if (id is! String || method is! String) {
        return null;
      }
      var params = result[Request.PARAMS];
      Request request = new Request(id, method);
      if (params is Map) {
        params.forEach((String key, Object value) {
          request.setParameter(key, value);
        });
      } else if (params != null) {
        return null;
      }
      return request;
    } catch (exception) {
      return null;
    }
  }

  /**
   * Return the value of the parameter with the given [name], or [defaultValue]
   * if there is no such parameter associated with this request.
   */
  RequestDatum getParameter(String name, defaultValue) {
    if (!params.containsKey(name)) {
      return new RequestDatum(this, "default for $name", defaultValue);
    }
    return new RequestDatum(this, name, params[name]);
  }

  /**
   * Return the value of the parameter with the given [name], or throw a
   * [RequestFailure] exception with an appropriate error message if there is no
   * such parameter associated with this request.
   */
  RequestDatum getRequiredParameter(String name) {
    if (!params.containsKey(name)) {
      throw new RequestFailure(new Response.missingRequiredParameter(this, name));
    }
    return new RequestDatum(this, name, params[name]);
  }

  /**
   * Set the value of the parameter with the given [name] to the given [value].
   */
  void setParameter(String name, Object value) {
    params[name] = value;
  }

  /**
   * 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() {
    Map<String, Object> jsonObject = new HashMap<String, Object>();
    jsonObject[ID] = id;
    jsonObject[METHOD] = method;
    if (params.isNotEmpty) {
      jsonObject[PARAMS] = params;
    }
    return jsonObject;
  }
}

/**
 * Instances of the class [RequestDatum] wrap a piece of data from a
 * request parameter, and contain accessor methods which automatically validate
 * and convert the data into the appropriate form.
 */
class RequestDatum {
  /**
   * Request object that should be referred to in any errors that are
   * generated.
   */
  final Request request;

  /**
   * String description of how [datum] was obtained from the request.
   */
  final String path;

  /**
   * Value to be decoded and validated.
   */
  final dynamic datum;

  /**
   * Create a RequestDatum for decoding and validating [datum], which refers to
   * [request] in any errors it reports.
   */
  RequestDatum(this.request, this.path, this.datum);

  /**
   * Validate that the datum is a Map containing the given [key], and return
   * a [RequestDatum] containing the corresponding value.
   */
  RequestDatum operator [](String key) {
    Map<String, Object> map = _asMap();
    if (!map.containsKey(key)) {
      throw new RequestFailure(new Response.invalidParameter(request, path,
          "contain key '$key'"));
    }
    return new RequestDatum(request, "$path.$key", map[key]);
  }

  /**
   * Return `true` if the datum is a Map containing the given [key].
   */
  bool hasKey(String key) {
    return _asMap().containsKey(key);
  }

  /**
   * Validate that the datum is a Map, and return an iterable for its keys.
   */
  Iterable<String> get keys => _asMap().keys;

  /**
   * Validate that the datum is a Map whose keys are strings, and call [f] on
   * each key/value pair in the map.
   */
  void forEachMap(void f(String key, RequestDatum value)) {
    _asMap().forEach((String key, value) {
      f(key, new RequestDatum(request, "$path.$key", value));
    });
  }

  /**
   * Validate that the datum is an integer (or a string that can be parsed
   * as an integer), and return the int.
   */
  int asInt() {
    if (datum is int) {
      return datum;
    } else if (datum is String) {
      return int.parse(datum, onError: (String value) {
        throw new RequestFailure(new Response.invalidParameter(request, path,
            "be an integer"));
      });
    }
    throw new RequestFailure(new Response.invalidParameter(request, path,
        "be an integer"));
  }

  /**
   * Validate that the datum is a boolean (or a string that can be parsed
   * as a boolean), and return the bool.
   *
   * The value is typically the result of invoking either [getParameter] or
   * [getRequiredParameter].
   */
  bool asBool() {
    if (datum is bool) {
      return datum;
    } else if (datum == 'true') {
      return true;
    } else if (datum == 'false') {
      return false;
    }
    throw new RequestFailure(new Response.invalidParameter(request, datum,
        "be a boolean"));
  }

  /**
   * Determine if the datum is a list.  Note: null is considered a synonym for
   * the empty list.
   */
  bool get isList {
    return datum == null || datum is List;
  }

  /**
   * Validate that the datum is a list, and return it in raw form.
   */
  List _asList() {
    if (!isList) {
      throw new RequestFailure(new Response.invalidParameter(request, path,
          "be a list"));
    }
    if (datum == null) {
      return [];
    } else {
      return datum;
    }
  }

  /**
   * Validate that the datum is a list, and return a list where each element in
   * the datum has been converted using the provided function.
   */
  List asList(elementConverter(RequestDatum datum)) {
    List result = [];
    List list = _asList();
    for (int i = 0; i < list.length; i++) {
      result.add(elementConverter(new RequestDatum(request, "$path.$i", list[i])));
    }
    return result;
  }

  /**
   * Validate that the datum is a string, and return it.
   */
  String asString() {
    if (datum is! String) {
      throw new RequestFailure(new Response.invalidParameter(request, path,
          "be a string"));
    }
    return datum;
  }

  /**
   * Determine if the datum is a list of strings.  Note: null is considered a
   * synonym for the empty list.
   */
  bool get isStringList {
    if (!isList) {
      return false;
    }
    for (var element in _asList()) {
      if (element is! String) {
        return false;
      }
    }
    return true;
  }

  /**
   * Validate that the datum is a list of strings, and return it.  Note: null
   * is considered a synonym for the empty list.
   */
  List<String> asStringList() {
    if (!isStringList) {
      throw new RequestFailure(new Response.invalidParameter(request, path,
          "be a list of strings"));
    }
    return _asList();
  }

  /**
   * Validate that the datum is a list of strings, and convert it into [Enum]s.
   */
  Set<Enum2> asEnumSet(List<Enum2> allValues) {
    Set values = new Set();
    for (String name in asStringList()) {
      Enum2 value = Enum2.valueOf(allValues, name);
      if (value == null) {
        throw new RequestFailure(new Response.invalidParameter(request, path,
            "be a list of names from the list $allValues"));
      }
      values.add(value);
    }
    return values;
  }

  /**
   * Determine if the datum is a map.  Note: null is considered a synonym for
   * the empty map.
   */
  bool get isMap {
    return datum == null || datum is Map;
  }

  /**
   * Validate that the datum is a map, and return it in raw form.
   */
  Map<String, Object> _asMap() {
    if (!isMap) {
      throw new RequestFailure(new Response.invalidParameter(request, path,
          "be a map"));
    }
    if (datum == null) {
      return {};
    } else {
      return datum;
    }
  }

  /**
   * Determine if the datum is a map whose values are all strings.  Note: null
   * is considered a synonym for the empty map.
   *
   * Note: we can safely assume that the keys are all strings, since JSON maps
   * cannot have any other key type.
   */
  bool get isStringMap {
    if (!isMap) {
      return false;
    }
    for (var value in _asMap().values) {
      if (value is! String) {
        return false;
      }
    }
    return true;
  }

  /**
   * Validate that the datum is a map from strings to strings, and return it.
   */
  Map<String, String> asStringMap() {
    if (!isStringMap) {
      throw new RequestFailure(new Response.invalidParameter(request, path,
          "be a string map"));
    }
    return _asMap();
  }

  /**
   * Determine if the datum is a map whose values are all string lists.  Note:
   * null is considered a synonym for the empty map.
   *
   * Note: we can safely assume that the keys are all strings, since JSON maps
   * cannot have any other key type.
   */
  bool get isStringListMap {
    if (!isMap) {
      return false;
    }
    for (var value in _asMap().values) {
      if (value is! List) {
        return false;
      }
      for (var listItem in value) {
        if (listItem is! String) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * Validate that the datum is a map from strings to string lists, and return
   * it.
   */
  Map<String, List<String>> asStringListMap() {
    if (!isStringListMap) {
      throw new RequestFailure(new Response.invalidParameter(request, path,
          "be a string list map"));
    }
    return _asMap();
  }

  bool get isNull => datum == null;
}

/**
 * Instances of the class [Response] represent a response to a request.
 */
class Response {
  /**
   * The [Response] instance that is returned when a real [Response] cannot
   * be provided at the moment.
   */
  static final Response DELAYED_RESPONSE = new Response('DELAYED_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 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;

  /**
   * 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 an [error] is provided then the response will
   * represent an error condition.
   */
  Response(this.id, [this.error]);

  /**
   * Initialize a newly created instance to represent an error condition caused
   * by a [request] referencing a context that does not exist.
   */
  Response.contextDoesNotExist(Request request)
    : this(request.id, new RequestError('NONEXISTENT_CONTEXT', 'Context does not exist'));

  /**
   * 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, new RequestError('INVALID_PARAMETER',
          "Expected parameter $path to $expectation"));

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

  /**
   * Initialize a newly created instance to represent an error condition caused
   * by a [request] that does not have a required parameter.
   */
  Response.missingRequiredParameter(Request request, String parameterName)
    : this(request.id, new RequestError('MISSING_PARAMETER', 'Missing required parameter: $parameterName'));

  /**
   * Initialize a newly created instance to represent an error condition caused
   * by a [request] that takes a set of analysis options but for which an
   * unknown analysis option was provided.
   */
  Response.unknownAnalysisOption(Request request, String optionName)
    : this(request.id, new RequestError('UNKNOWN_ANALYSIS_OPTION', 'Unknown analysis option: "$optionName"'));

  /**
   * 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, new RequestError('UNKNOWN_REQUEST', 'Unknown request'));

  Response.contextAlreadyExists(Request request)
    : this(request.id, new RequestError('CONTENT_ALREADY_EXISTS', 'Context already exists'));

  Response.unsupportedFeature(String requestId, String message)
    : this(requestId, new RequestError('UNSUPPORTED_FEATURE', message));

  /**
   * Initialize a newly created instance to represent an error condition caused
   * by a `analysis.setSubscriptions` [request] that includes an unknown
   * analysis service name.
   */
  Response.unknownAnalysisService(Request request, String name)
    : this(request.id, new RequestError('UNKNOWN_ANALYSIS_SERVICE', 'Unknown analysis service: "$name"'));

  /**
   * Initialize a newly created instance to represent an error condition caused
   * by a `analysis.setPriorityFiles` [request] that includes one or more files
   * that are not being analyzed.
   */
  Response.unanalyzedPriorityFiles(Request request, String fileNames)
    : this(request.id, new RequestError('UNANALYZED_PRIORITY_FILES', "Unanalyzed files cannot be a priority: '$fileNames'"));

  /**
   * Initialize a newly created instance to represent an error condition caused
   * by a `analysis.updateOptions` [request] that includes an unknown analysis
   * option.
   */
  Response.unknownOptionName(Request request, String optionName)
    : this(request.id, new RequestError('UNKNOWN_OPTION_NAME', 'Unknown analysis option: "$optionName"'));

  /**
   * Initialize a newly created instance to represent an error condition caused
   * by an error during `analysis.getErrors`.
   */
  Response.getErrorsError(Request request, String message)
    : this(
        request.id,
        new RequestError('GET_ERRORS_ERROR', 'Error during `analysis.getErrors`: $message.'));

  /**
   * Initialize a newly created instance based upon the given JSON data
   */
  factory Response.fromJson(Map<String, Object> json) {
    try {
      Object id = json[Response.ID];
      if (id is! String) {
        return null;
      }
      Object error = json[Response.ERROR];
      Object result = json[Response.RESULT];
      Response response;
      if (error is Map) {
        response = new Response(id, new RequestError.fromJson(error));
      } else {
        response = new Response(id);
      }
      if (result is Map) {
        result.forEach((String key, Object value) {
          response.setResult(key, value);
        });
      }
      return response;
    } catch (exception) {
      return null;
    }
  }

  /**
   * Return the value of the result field with the given [name].
   */
  Object getResult(String name) {
    return result == null ? null : result[name];
  }

  /**
   * Set the value of the result field with the given [name] to the given [value].
   */
  void setResult(String name, Object value) {
    if (result == null) {
      result = new HashMap<String, Object>();
    }
    result[name] = _toJson(value);
  }

  /**
   * Set the result to be an empty map.
   */
  void setEmptyResult() {
    result = new HashMap<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() {
    Map<String, Object> jsonObject = new HashMap<String, Object>();
    jsonObject[ID] = id;
    if (error != null) {
      jsonObject[ERROR] = error.toJson();
    }
    if (result != null) {
      jsonObject[RESULT] = result;
    }
    return jsonObject;
  }
}

/**
 * Instances of the class [RequestError] represent information about an error
 * that occurred while attempting to respond to a [Request].
 */
class RequestError {
  /**
   * The name of the JSON attribute containing the code that uniquely identifies
   * the error that occurred.
   */
  static const String CODE = 'code';

  /**
   * The name of the JSON attribute containing an object with additional data
   * related to the error.
   */
  static const String DATA = 'data';

  /**
   * The name of the JSON attribute containing a short description of the error.
   */
  static const String MESSAGE = 'message';

  /**
   * An error code indicating a parse error. Invalid JSON was received by the
   * server. An error occurred on the server while parsing the JSON text.
   */
  static const String CODE_PARSE_ERROR = 'PARSE_ERROR';

  /**
   * An error code indicating that the analysis server has already been
   * started (and hence won't accept new connections).
   */
  static const String CODE_SERVER_ALREADY_STARTED = 'SERVER_ALREADY_STARTED';

  /**
   * An error code indicating an invalid request. The JSON sent is not a valid
   * [Request] object.
   */
  static const String CODE_INVALID_REQUEST = 'INVALID_REQUEST';

  /**
   * An error code indicating a method not found. The method does not exist or
   * is not currently available.
   */
  static const String CODE_METHOD_NOT_FOUND = 'METHOD_NOT_FOUND';

  /**
   * An error code indicating one or more invalid parameters.
   */
  static const String CODE_INVALID_PARAMS = 'INVALID_PARAMS';

  /**
   * An error code indicating an internal error.
   */
  static const String CODE_INTERNAL_ERROR = 'INTERNAL_ERROR';

  /**
   * An error code indicating a problem using the specified Dart SDK.
   */
  static const String CODE_SDK_ERROR = 'SDK_ERROR';

  /**
   * An error code indicating a problem during 'analysis.getErrors'.
   */
  static const String CODE_ANALISYS_GET_ERRORS_ERROR = 'ANALYSIS_GET_ERRORS_ERROR';

  /**
   * The code that uniquely identifies the error that occurred.
   */
  final String code;

  /**
   * A short description of the error.
   */
  final String message;

  /**
   * A table mapping the names of notification parameters to their values.
   */
  final Map<String, Object> data = new HashMap<String, Object>();

  /**
   * Initialize a newly created [Error] to have the given [code] and [message].
   */
  RequestError(this.code, this.message);

  /**
   * Initialize a newly created [Error] to indicate a parse error. Invalid JSON
   * was received by the server. An error occurred on the server while parsing
   * the JSON text.
   */
  RequestError.parseError() : this(CODE_PARSE_ERROR, "Parse error");

  /**
   * Initialize a newly created [Error] to indicate that the analysis server
   * has already been started (and hence won't accept new connections).
   */
  RequestError.serverAlreadyStarted()
    : this(CODE_SERVER_ALREADY_STARTED, "Server already started");

  /**
   * Initialize a newly created [Error] to indicate an invalid request. The
   * JSON sent is not a valid [Request] object.
   */
  RequestError.invalidRequest() : this(CODE_INVALID_REQUEST, "Invalid request");

  /**
   * Initialize a newly created [Error] to indicate that a method was not found.
   * Either the method does not exist or is not currently available.
   */
  RequestError.methodNotFound() : this(CODE_METHOD_NOT_FOUND, "Method not found");

  /**
   * Initialize a newly created [Error] to indicate one or more invalid
   * parameters.
   */
  RequestError.invalidParameters() : this(CODE_INVALID_PARAMS, "Invalid parameters");

  /**
   * Initialize a newly created [Error] to indicate an internal error.
   */
  RequestError.internalError() : this(CODE_INTERNAL_ERROR, "Internal error");

  /**
   * Initialize a newly created [Error] from the given JSON.
   */
  factory RequestError.fromJson(Map<String, Object> json) {
    try {
      String code = json[RequestError.CODE];
      String message = json[RequestError.MESSAGE];
      Map<String, Object> data = json[RequestError.DATA];
      RequestError requestError = new RequestError(code, message);
      if (data != null) {
        data.forEach((String key, Object value) {
          requestError.setData(key, value);
        });
      }
      return requestError;
    } catch (exception) {
      return null;
    }
  }

  /**
   * Return the value of the data with the given [name], or `null` if there is
   * no such data associated with this error.
   */
  Object getData(String name) => data[name];

  /**
   * Set the value of the data with the given [name] to the given [value].
   */
  void setData(String name, Object value) {
    data[name] = value;
  }

  /**
   * 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() {
    Map<String, Object> jsonObject = new HashMap<String, Object>();
    jsonObject[CODE] = code;
    jsonObject[MESSAGE] = message;
    if (!data.isEmpty) {
      jsonObject[DATA] = data;
    }
    return jsonObject;
  }

  @override
  String toString() => toJson().toString();
}

/**
 * Instances of the class [Notification] represent a notification from the
 * server about an event that occurred.
 */
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.
   */
  final Map<String, Object> params = new HashMap<String, Object>();

  /**
   * Initialize a newly created [Notification] to have the given [event] name.
   */
  Notification(this.event);

  /**
   * Initialize a newly created instance based upon the given JSON data
   */
  factory Notification.fromJson(Map<String, Object> json) {
    try {
      String event = json[Notification.EVENT];
      Object params = json[Notification.PARAMS];
      Notification notification = new Notification(event);
      if (params is Map) {
        params.forEach((String key, Object value) {
          notification.setParameter(key, value);
        });
      }
      return notification;
    } catch (exception) {
      return null;
    }
  }

  /**
   * Return the value of the parameter with the given [name], or `null` if there
   * is no such parameter associated with this notification.
   */
  Object getParameter(String name) => params[name];

  /**
   * Set the value of the parameter with the given [name] to the given [value].
   */
  void setParameter(String name, Object value) {
    params[name] = _toJson(value);
  }

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

/**
 * Instances of the class [RequestHandler] implement a handler that can handle
 * requests and produce responses for them.
 */
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);
}

/**
 * Instances of the class [RequestFailure] represent an exception that occurred
 * during the handling of a request that requires that an error be returned to
 * the client.
 */
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 reponse.
   */
  RequestFailure(this.response);
}

/**
 * Returns a JSON presention of [value].
 */
_toJson(Object value) {
  if (value is HasToJson) {
    return value.toJson();
  }
  if (value is Iterable) {
    return value.map((item) => _toJson(item)).toList();
  }
  return value;
}
