// 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 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. The table
   * should be empty if there was an error.
   */
  final Map<String, Object> result = new HashMap<String, Object>();

  /**
   * 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[name];
  }

  /**
   * Set the value of the result field with the given [name] to the given [value].
   */
  void setResult(String name, Object value) {
    result[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 = new HashMap<String, Object>();
    jsonObject[ID] = id;
    if (error != null) {
      jsonObject[ERROR] = error.toJson();
    }
    if (!result.isEmpty) {
      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;
}
