// 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 json_rpc_2.parameters;

import 'dart:convert';

import 'exception.dart';

/// A wrapper for the parameters to a server method.
///
/// JSON-RPC 2.0 allows parameters that are either a list or a map. This class
/// provides functions that not only assert that the parameters object is the
/// correct type, but also that the expected arguments exist and are themselves
/// the correct type.
///
/// Example usage:
///
///     server.registerMethod("subtract", (params) {
///       return params["minuend"].asNum - params["subtrahend"].asNum;
///     });
class Parameters {
  /// The name of the method that this request called.
  final String method;

  /// The underlying value of the parameters object.
  ///
  /// If this is accessed for a [Parameter] that was not passed, the request
  /// will be automatically rejected. To avoid this, use [Parameter.valueOr].
  final value;

  Parameters(this.method, this.value);

  /// Returns a single parameter.
  ///
  /// If [key] is a [String], the request is expected to provide named
  /// parameters. If it's an [int], the request is expected to provide
  /// positional parameters. Requests that don't do so will be rejected
  /// automatically.
  ///
  /// Whether or not the given parameter exists, this returns a [Parameter]
  /// object. If a parameter's value is accessed through a getter like [value]
  /// or [Parameter.asNum], the request will be rejected if that parameter
  /// doesn't exist. On the other hand, if it's accessed through a method with a
  /// default value like [Parameter.valueOr] or [Parameter.asNumOr], the default
  /// value will be returned.
  Parameter operator [](key) {
    if (key is int) {
      _assertPositional();
      if (key < value.length) {
        return new Parameter._(method, value[key], this, key);
      } else {
        return new _MissingParameter(method, this, key);
      }
    } else if (key is String) {
      _assertNamed();
      if (value.containsKey(key)) {
        return new Parameter._(method, value[key], this, key);
      } else {
        return new _MissingParameter(method, this, key);
      }
    } else {
      throw new ArgumentError('Parameters[] only takes an int or a string, was '
          '"$key".');
    }
  }

  /// Asserts that [value] exists and is a [List] and returns it.
  List get asList {
    _assertPositional();
    return value;
  }

  /// Asserts that [value] exists and is a [Map] and returns it.
  Map get asMap {
    _assertNamed();
    return value;
  }

  /// Asserts that [value] is a positional argument list.
  void _assertPositional() {
    if (value is List) return;
    throw new RpcException.invalidParams('Parameters for method "$method" '
        'must be passed by position.');
  }

  /// Asserts that [value] is a named argument map.
  void _assertNamed() {
    if (value is Map) return;
    throw new RpcException.invalidParams('Parameters for method "$method" '
        'must be passed by name.');
  }
}

/// A wrapper for a single parameter to a server method.
///
/// This provides numerous functions for asserting the type of the parameter in
/// question. These functions each have a version that asserts that the
/// parameter exists (for example, [asNum] and [asString]) and a version that
/// returns a default value if the parameter doesn't exist (for example,
/// [asNumOr] and [asStringOr]). If an assertion fails, the request is
/// automatically rejected.
///
/// This extends [Parameters] to make it easy to access nested parameters. For
/// example:
///
///     // "params.value" is "{'scores': {'home': [5, 10, 17]}}"
///     params['scores']['home'][2].asInt // => 17
class Parameter extends Parameters {
  // The parent parameters, used to construct [_path].
  final Parameters _parent;

  /// The key used to access [this], used to construct [_path].
  final _key;

  /// A human-readable representation of the path of getters used to get this.
  ///
  /// Named parameters are represented as `.name`, whereas positional parameters
  /// are represented as `[index]`. For example: `"foo[0].bar.baz"`. Named
  /// parameters that contain characters that are neither alphanumeric,
  /// underscores, or hyphens will be JSON-encoded. For example: `"foo
  /// bar"."baz.bang"`. If quotes are used for an individual component, they
  /// won't be used for the entire string.
  ///
  /// An exception is made for single-level parameters. A single-level
  /// positional parameter is just represented by the index plus one, because
  /// "parameter 1" is clearer than "parameter [0]". A single-level named
  /// parameter is represented by that name in quotes.
  String get _path {
    if (_parent is! Parameter) {
      return _key is int ? (_key + 1).toString() : JSON.encode(_key);
    }

    quoteKey(key) {
      if (key.contains(new RegExp(r'[^a-zA-Z0-9_-]'))) return JSON.encode(key);
      return key;
    }

    computePath(params) {
      if (params._parent is! Parameter) {
        return params._key is int ? "[${params._key}]" : quoteKey(params._key);
      }

      var path = computePath(params._parent);
      return params._key is int ?
          "$path[${params._key}]" : "$path.${quoteKey(params._key)}";
    }

    return computePath(this);
  }

  /// Whether this parameter exists.
  final exists = true;

  Parameter._(String method, value, this._parent, this._key)
      : super(method, value);

  /// Returns [value], or [defaultValue] if this parameter wasn't passed.
  valueOr(defaultValue) => value;

  /// Asserts that [value] exists and is a number and returns it.
  ///
  /// [asNumOr] may be used to provide a default value instead of rejecting the
  /// request if [value] doesn't exist.
  num get asNum => _getTyped('a number', (value) => value is num);

  /// Asserts that [value] is a number and returns it.
  ///
  /// If [value] doesn't exist, this returns [defaultValue].
  num asNumOr(num defaultValue) => asNum;

  /// Asserts that [value] exists and is an integer and returns it.
  ///
  /// [asIntOr] may be used to provide a default value instead of rejecting the
  /// request if [value] doesn't exist.
  ///
  /// Note that which values count as integers varies between the Dart VM and
  /// dart2js. The value `1.0` will be considered an integer under dart2js but
  /// not under the VM.
  int get asInt => _getTyped('an integer', (value) => value is int);

  /// Asserts that [value] is an integer and returns it.
  ///
  /// If [value] doesn't exist, this returns [defaultValue].
  ///
  /// Note that which values count as integers varies between the Dart VM and
  /// dart2js. The value `1.0` will be considered an integer under dart2js but
  /// not under the VM.
  int asIntOr(int defaultValue) => asInt;

  /// Asserts that [value] exists and is a boolean and returns it.
  ///
  /// [asBoolOr] may be used to provide a default value instead of rejecting the
  /// request if [value] doesn't exist.
  bool get asBool => _getTyped('a boolean', (value) => value is bool);

  /// Asserts that [value] is a boolean and returns it.
  ///
  /// If [value] doesn't exist, this returns [defaultValue].
  bool asBoolOr(bool defaultValue) => asBool;

  /// Asserts that [value] exists and is a string and returns it.
  ///
  /// [asStringOr] may be used to provide a default value instead of rejecting
  /// the request if [value] doesn't exist.
  String get asString => _getTyped('a string', (value) => value is String);

  /// Asserts that [value] is a string and returns it.
  ///
  /// If [value] doesn't exist, this returns [defaultValue].
  String asStringOr(String defaultValue) => asString;

  /// Asserts that [value] exists and is a [List] and returns it.
  ///
  /// [asListOr] may be used to provide a default value instead of rejecting the
  /// request if [value] doesn't exist.
  List get asList => _getTyped('an Array', (value) => value is List);

  /// Asserts that [value] is a [List] and returns it.
  ///
  /// If [value] doesn't exist, this returns [defaultValue].
  List asListOr(List defaultValue) => asList;

  /// Asserts that [value] exists and is a [Map] and returns it.
  ///
  /// [asMapOr] may be used to provide a default value instead of rejecting the
  /// request if [value] doesn't exist.
  Map get asMap => _getTyped('an Object', (value) => value is Map);

  /// Asserts that [value] is a [Map] and returns it.
  ///
  /// If [value] doesn't exist, this returns [defaultValue].
  Map asMapOr(Map defaultValue) => asMap;

  /// Asserts that [value] exists, is a string, and can be parsed as a
  /// [DateTime] and returns it.
  ///
  /// [asDateTimeOr] may be used to provide a default value instead of rejecting
  /// the request if [value] doesn't exist.
  DateTime get asDateTime => _getParsed('date/time', DateTime.parse);

  /// Asserts that [value] exists, is a string, and can be parsed as a
  /// [DateTime] and returns it.
  ///
  /// If [value] doesn't exist, this returns [defaultValue].
  DateTime asDateTimeOr(DateTime defaultValue) => asDateTime;

  /// Asserts that [value] exists, is a string, and can be parsed as a
  /// [Uri] and returns it.
  ///
  /// [asUriOr] may be used to provide a default value instead of rejecting the
  /// request if [value] doesn't exist.
  Uri get asUri => _getParsed('URI', Uri.parse);

  /// Asserts that [value] exists, is a string, and can be parsed as a
  /// [Uri] and returns it.
  ///
  /// If [value] doesn't exist, this returns [defaultValue].
  Uri asUriOr(Uri defaultValue) => asUri;

  /// Get a parameter named [named] that matches [test], or the value of calling
  /// [orElse].
  ///
  /// [type] is used for the error message. It should begin with an indefinite
  /// article.
  _getTyped(String type, bool test(value)) {
    if (test(value)) return value;
    throw new RpcException.invalidParams('Parameter $_path for method '
        '"$method" must be $type, but was ${JSON.encode(value)}.');
  }

  _getParsed(String description, parse(String value)) {
    var string = asString;
    try {
      return parse(string);
    } on FormatException catch (error) {
      // DateTime.parse doesn't actually include any useful information in the
      // FormatException, just the string that was being parsed. There's no use
      // in including that in the RPC exception. See issue 17753.
      var message = error.message;
      if (message == string) {
        message = '';
      } else {
        message = '\n$message';
      }

      throw new RpcException.invalidParams('Parameter $_path for method '
          '"$method" must be a valid $description, but was '
          '${JSON.encode(string)}.$message');
    }
  }

  void _assertPositional() {
    // Throw the standard exception for a mis-typed list.
    asList;
  }

  void _assertNamed() {
    // Throw the standard exception for a mis-typed map.
    asMap;
  }
}

/// A subclass of [Parameter] representing a missing parameter.
class _MissingParameter extends Parameter {
  get value {
    throw new RpcException.invalidParams('Request for method "$method" is '
        'missing required parameter $_path.');
  }

  final exists = false;

  _MissingParameter(String method, Parameters parent, key)
      : super._(method, null, parent, key);

  valueOr(defaultValue) => defaultValue;

  num asNumOr(num defaultValue) => defaultValue;

  int asIntOr(int defaultValue) => defaultValue;

  bool asBoolOr(bool defaultValue) => defaultValue;

  String asStringOr(String defaultValue) => defaultValue;

  List asListOr(List defaultValue) => defaultValue;

  Map asMapOr(Map defaultValue) => defaultValue;

  DateTime asDateTimeOr(DateTime defaultValue) => defaultValue;

  Uri asUriOr(Uri defaultValue) => defaultValue;
}
