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

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;
}
