library googleapis.common_internal;

import "dart:async";
import "dart:convert";
import "dart:collection" as collection;

import "package:crypto/crypto.dart" as crypto;
import "../common/common.dart" as common_external;
import "package:http/http.dart" as http;

const String USER_AGENT_STRING =
    'google-api-dart-client googleapis/0.3.1';

const CONTENT_TYPE_JSON_UTF8 = 'application/json; charset=utf-8';

/**
 * Base class for all API clients, offering generic methods for
 * HTTP Requests to the API
 */
class ApiRequester {
  final http.Client _httpClient;
  final String _rootUrl;
  final String _basePath;

  ApiRequester(this._httpClient, this._rootUrl, this._basePath) {
    assert(_rootUrl.endsWith('/'));
  }


  /**
   * Sends a HTTPRequest using [method] (usually GET or POST) to [requestUrl]
   * using the specified [urlParams] and [queryParams]. Optionally include a
   * [body] and/or [uploadMedia] in the request.
   *
   * If [uploadMedia] was specified [downloadOptions] must be
   * [DownloadOptions.Metadata] or `null`.
   *
   * If [downloadOptions] is [DownloadOptions.Metadata] the result will be
   * decoded as JSON.
   *
   * If [downloadOptions] is `null` the result will be a Future completing with
   * `null`.
   *
   * Otherwise the result will be downloaded as a [common_external.Media]
   */
  Future request(String requestUrl, String method,
                 {String body, Map queryParams,
                  common_external.Media uploadMedia,
                  common_external.UploadOptions uploadOptions,
                  common_external.DownloadOptions downloadOptions:
                  common_external.DownloadOptions.Metadata}) {
    if (uploadMedia != null &&
        downloadOptions != common_external.DownloadOptions.Metadata) {
      throw new ArgumentError('When uploading a [Media] you cannot download a '
                              '[Media] at the same time!');
    }
    common_external.ByteRange downloadRange;
    if (downloadOptions is common_external.PartialDownloadOptions &&
        !downloadOptions.isFullDownload) {
      downloadRange = downloadOptions.range;
    }

    return _request(requestUrl, method, body, queryParams,
                    uploadMedia, uploadOptions,
                    downloadOptions,
                    downloadRange)
        .then(_validateResponse).then((http.StreamedResponse response) {
      if (downloadOptions == null) {
        // If no download options are given, the response is of no interest
        // and we will drain the stream.
        return response.stream.drain();
      } else if (downloadOptions == common_external.DownloadOptions.Metadata) {
        // Downloading JSON Metadata
        var stringStream = _decodeStreamAsText(response);
        if (stringStream != null) {
          return stringStream.join('').then((String bodyString) {
            if (bodyString == '') return null;
            return JSON.decode(bodyString);
          });
        } else {
          throw new common_external.ApiRequestError(
              "Unable to read response with content-type "
              "${response.headers['content-type']}.");
        }
      } else {
        // Downloading Media.
        var contentType = response.headers['content-type'];
        if (contentType == null) {
          throw new common_external.ApiRequestError(
              "No 'content-type' header in media response.");
        }
        var contentLength;
        try {
          contentLength = int.parse(response.headers['content-length']);
        } catch (_) {
          // We silently ignore errors here. If no content-length was specified
          // we use `null`.
          // Please note that the code below still asserts the content-length
          // is correct for range downloads.
        }

        if (downloadRange != null) {
          if (contentLength != downloadRange.length) {
            throw new common_external.ApiRequestError(
                "Content length of response does not match requested range "
                "length.");
          }
          var contentRange = response.headers['content-range'];
          var expected = 'bytes ${downloadRange.start}-${downloadRange.end}/';
          if (contentRange == null || !contentRange.startsWith(expected)) {
            throw new common_external.ApiRequestError("Attempting partial "
                "download but got invalid 'Content-Range' header "
                "(was: $contentRange, expected: $expected).");
          }
        }

        return new common_external.Media(
            response.stream, contentLength, contentType: contentType);
      }
    });
  }

  Future _request(String requestUrl, String method,
                  String body, Map queryParams,
                  common_external.Media uploadMedia,
                  common_external.UploadOptions uploadOptions,
                  common_external.DownloadOptions downloadOptions,
                  common_external.ByteRange downloadRange) {
    bool downloadAsMedia =
        downloadOptions != null &&
        downloadOptions != common_external.DownloadOptions.Metadata;

    if (queryParams == null) queryParams = {};

    if (uploadMedia != null) {
      if (uploadOptions is common_external.ResumableUploadOptions) {
        queryParams['uploadType'] = const ['resumable'];
      } else if (body == null) {
        queryParams['uploadType'] = const ['media'];
      } else {
        queryParams['uploadType'] = const ['multipart'];
      }
    }

    if (downloadAsMedia) {
      queryParams['alt'] = const ['media'];
    } else if (downloadOptions != null) {
      queryParams['alt'] = const ['json'];
    }

    var path;
    if (requestUrl.startsWith('/')) {
      path ="$_rootUrl${requestUrl.substring(1)}";
    } else {
      path ="$_rootUrl${_basePath}$requestUrl";
    }

    bool containsQueryParameter = path.contains('?');
    addQueryParameter(String name, String value) {
      name = Escaper.escapeQueryComponent(name);
      value = Escaper.escapeQueryComponent(value);
      if (containsQueryParameter) {
        path = '$path&$name=$value';
      } else {
        path = '$path?$name=$value';
      }
      containsQueryParameter = true;
    }
    queryParams.forEach((String key, List<String> values) {
      for (var value in values) {
        addQueryParameter(key, value);
      }
    });

    var uri = Uri.parse(path);

    Future simpleUpload() {
      var bodyStream = uploadMedia.stream;
      var request = new RequestImpl(method, uri, bodyStream);
      request.headers.addAll({
        'user-agent' : USER_AGENT_STRING,
        'content-type' : uploadMedia.contentType,
        'content-length' : '${uploadMedia.length}'
      });
      return _httpClient.send(request);
    }

    Future simpleRequest() {
      var length = 0;
      var bodyController = new StreamController<List<int>>();
      if (body != null) {
        var bytes = UTF8.encode(body);
        bodyController.add(bytes);
        length = bytes.length;
      }
      bodyController.close();

      var headers;
      if (downloadRange != null) {
        headers = {
          'user-agent' : USER_AGENT_STRING,
          'content-type' : CONTENT_TYPE_JSON_UTF8,
          'content-length' : '$length',
          'range' :  'bytes=${downloadRange.start}-${downloadRange.end}',
        };
      } else {
        headers = {
          'user-agent' : USER_AGENT_STRING,
          'content-type' : CONTENT_TYPE_JSON_UTF8,
          'content-length' : '$length',
        };
      }

      var request = new RequestImpl(method, uri, bodyController.stream);
      request.headers.addAll(headers);
      return _httpClient.send(request);
    }

    if (uploadMedia != null) {
      // Three upload types:
      // 1. Resumable: Upload of data + metdata with multiple requests.
      // 2. Simple: Upload of media.
      // 3. Multipart: Upload of data + metadata.

      if (uploadOptions is common_external.ResumableUploadOptions) {
        var helper = new ResumableMediaUploader(
            _httpClient, uploadMedia, body, uri, method, uploadOptions);
        return helper.upload();
      }

      if (uploadMedia.length == null) {
        throw new ArgumentError(
            'For non-resumable uploads you need to specify the length of the '
            'media to upload.');
      }

      if (body == null) {
        return simpleUpload();
      } else {
        var uploader = new MultipartMediaUploader(
            _httpClient, uploadMedia, body, uri, method);
        return uploader.upload();
      }
    }
    return simpleRequest();
  }
}


/**
 * Does media uploads using the multipart upload protocol.
 */
class MultipartMediaUploader {
  static final _boundary = '314159265358979323846';
  static final _base64Encoder = new Base64Encoder();

  final http.Client _httpClient;
  final common_external.Media _uploadMedia;
  final Uri _uri;
  final String _body;
  final String _method;

  MultipartMediaUploader(
      this._httpClient, this._uploadMedia, this._body, this._uri, this._method);

  Future<http.StreamedResponse> upload() {
    var base64MediaStream =
        _uploadMedia.stream.transform(_base64Encoder).transform(ASCII.encoder);
    var base64MediaStreamLength =
        Base64Encoder.lengthOfBase64Stream(_uploadMedia.length);

    // NOTE: We assume that [_body] is encoded JSON without any \r or \n in it.
    // This guarantees us that [_body] cannot contain a valid multipart
    // boundary.
    var bodyHead =
        '--$_boundary\r\n'
        "Content-Type: $CONTENT_TYPE_JSON_UTF8\r\n\r\n"
        + _body +
        '\r\n--$_boundary\r\n'
        "Content-Type: ${_uploadMedia.contentType}\r\n"
        "Content-Transfer-Encoding: base64\r\n\r\n";
    var bodyTail = '\r\n--$_boundary--';

    var totalLength =
        bodyHead.length + base64MediaStreamLength + bodyTail.length;

    var bodyController = new StreamController<List<int>>();
    bodyController.add(UTF8.encode(bodyHead));
    bodyController.addStream(base64MediaStream).then((_) {
      bodyController.add(UTF8.encode(bodyTail));
    }).catchError((error, stack) {
      bodyController.addError(error, stack);
    }).then((_) {
      bodyController.close();
    });

    var headers = {
        'user-agent' : USER_AGENT_STRING,
        'content-type' : "multipart/related; boundary=\"$_boundary\"",
        'content-length' : '$totalLength'
    };
    var bodyStream = bodyController.stream;
    var request = new RequestImpl(_method, _uri, bodyStream);
    request.headers.addAll(headers);
    return _httpClient.send(request);
  }
}


/**
 * Base64 encodes a stream of bytes.
 */
class Base64Encoder implements StreamTransformer<List<int>, String> {
  static int lengthOfBase64Stream(int lengthOfByteStream) {
    return ((lengthOfByteStream + 2) ~/ 3) * 4;
  }

  Stream<String> bind(Stream<List<int>> stream) {
    StreamController<String> controller;

    // Holds between 0 and 3 bytes and is used as a buffer.
    List<int> remainingBytes = [];

    void onData(List<int> bytes) {
      if ((remainingBytes.length + bytes.length) < 3) {
        remainingBytes.addAll(bytes);
        return;
      }
      int start;
      if (remainingBytes.length == 0) {
        start = 0;
      } else if (remainingBytes.length == 1) {
        remainingBytes.add(bytes[0]);
        remainingBytes.add(bytes[1]);
        start = 2;
      } else if (remainingBytes.length == 2) {
        remainingBytes.add(bytes[0]);
        start = 1;
      }

      // Convert & Send bytes from buffer (if necessary).
      if (remainingBytes.length > 0) {
        controller.add(crypto.CryptoUtils.bytesToBase64(remainingBytes));
        remainingBytes.clear();
      }

      int chunksOf3 = (bytes.length - start) ~/ 3;
      int end = start + 3 * chunksOf3;
      int remaining = bytes.length - end;

      // Convert & Send main bytes.
      if (start == 0 && end == bytes.length) {
        // Fast path if [bytes] are devisible by 3.
        controller.add(crypto.CryptoUtils.bytesToBase64(bytes));
      } else {
        controller.add(
            crypto.CryptoUtils.bytesToBase64(bytes.sublist(start, end)));

        // Buffer remaining bytes if necessary.
        if (end < bytes.length) {
          remainingBytes.addAll(bytes.sublist(end));
        }
      }
    }

    void onError(error, stack) {
      controller.addError(error, stack);
    }

    void onDone() {
      if (remainingBytes.length > 0) {
        controller.add(crypto.CryptoUtils.bytesToBase64(remainingBytes));
        remainingBytes.clear();
      }
      controller.close();
    }

    var subscription;
    controller = new StreamController<String>(
        onListen: () {
          subscription = stream.listen(
              onData, onError: onError, onDone: onDone);
        },
        onPause: () {
          subscription.pause();
        },
        onResume: () {
          subscription.resume();
        },
        onCancel: () {
          subscription.cancel();
        });
    return controller.stream;
  }
}


// TODO: Buffer less if we know the content length in advance.
/**
 * Does media uploads using the resumable upload protocol.
 */
class ResumableMediaUploader {
  final http.Client _httpClient;
  final common_external.Media _uploadMedia;
  final Uri _uri;
  final String _body;
  final String _method;
  final common_external.ResumableUploadOptions _options;

  ResumableMediaUploader(
      this._httpClient, this._uploadMedia, this._body, this._uri, this._method,
      this._options);

  /**
   * Returns the final [http.StreamedResponse] if the upload succeded and
   * completes with an error otherwise.
   *
   * The returned response stream has not been listened to.
   */
  Future<http.StreamedResponse> upload() {
    return _startSession().then((Uri uploadUri) {
      StreamSubscription subscription;

      var completer = new Completer<http.StreamedResponse>();
      bool completed = false;

      var chunkStack = new ChunkStack(_options.chunkSize);
      subscription = _uploadMedia.stream.listen((List<int> bytes) {
        chunkStack.addBytes(bytes);

        // Upload all but the last chunk.
        // The final send will be done in the [onDone] handler.
        bool hasPartialChunk = chunkStack.hasPartialChunk;
        if (chunkStack.length > 1 ||
            (chunkStack.length == 1 && hasPartialChunk)) {
          // Pause the input stream.
          subscription.pause();

          // Upload all chunks except the last one.
          var fullChunks;
          if (hasPartialChunk) {
            fullChunks = chunkStack.removeSublist(0, chunkStack.length);
          } else {
            fullChunks = chunkStack.removeSublist(0, chunkStack.length - 1);
          }
          Future.forEach(fullChunks,
                         (c) => _uploadChunkDrained(uploadUri, c)).then((_) {
            // All chunks uploaded, we can continue consuming data.
            subscription.resume();
          }).catchError((error, stack) {
            subscription.cancel();
            completed = true;
            completer.completeError(error, stack);
          });
        }
      }, onError: (error, stack) {
        subscription.cancel();
        if (!completed) {
          completed = true;
          completer.completeError(error, stack);
        }
      }, onDone: () {
        if (!completed) {
          chunkStack.finalize();

          var lastChunk;
          if (chunkStack.length == 1) {
            lastChunk = chunkStack.removeSublist(0, chunkStack.length).first;
          } else {
            completer.completeError(new StateError(
                'Resumable uploads need to result in at least one non-empty '
                'chunk at the end.'));
            return;
          }
          var end = lastChunk.endOfChunk;

          // Validate that we have the correct number of bytes if length was
          // specified.
          if (_uploadMedia.length != null) {
            if (end < _uploadMedia.length) {
              completer.completeError(new common_external.ApiRequestError(
                  'Received less bytes than indicated by [Media.length].'));
              return;
            } else if (end > _uploadMedia.length) {
              completer.completeError(
                  'Received more bytes than indicated by [Media.length].');
              return;
            }
          }

          // Upload last chunk and *do not drain the response* but complete
          // with it.
          _uploadChunkResumable(uploadUri, lastChunk, lastChunk: true)
              .then((response) {
            completer.complete(response);
          }).catchError((error, stack) {
            completer.completeError(error, stack);
          });
        }
      });

      return completer.future;
    });
  }

  /**
   * Starts a resumable upload.
   *
   * Returns the [Uri] which should be used for uploading all content.
   */
  Future<Uri> _startSession() {
    var length = 0;
    var bytes;
    if (_body != null) {
      bytes = UTF8.encode(_body);
      length = bytes.length;
    }
    var bodyStream = _bytes2Stream(bytes);

    var request = new RequestImpl(_method, _uri, bodyStream);
    request.headers.addAll({
      'user-agent' : USER_AGENT_STRING,
      'content-type' : CONTENT_TYPE_JSON_UTF8,
      'content-length' : '$length',
      'x-upload-content-type' : _uploadMedia.contentType,
      'x-upload-content-length' : '${_uploadMedia.length}',
    });

    return _httpClient.send(request).then((http.StreamedResponse response) {
      return response.stream.drain().then((_) {
        var uploadUri = response.headers['location'];
        if (response.statusCode != 200 || uploadUri == null) {
          throw new common_external.ApiRequestError(
              'Invalid response for resumable upload attempt '
              '(status was: ${response.statusCode})');
        }
        return Uri.parse(uploadUri);
      });
    });
  }

  /**
   * Uploads [chunk], retries upon server errors. The response stream will be
   * drained.
   */
  Future _uploadChunkDrained(Uri uri, ResumableChunk chunk) {
    return _uploadChunkResumable(uri, chunk).then((response) {
      return response.stream.drain();
    });
  }

  /**
   * Does repeated attempts to upload [chunk].
   */
  Future _uploadChunkResumable(Uri uri,
                               ResumableChunk chunk,
                               {bool lastChunk: false}) {
    tryUpload(int attemptsLeft) {
      return _uploadChunk(uri, chunk, lastChunk: lastChunk)
          .then((http.StreamedResponse response) {
        var status = response.statusCode;
        if (attemptsLeft > 0 &&
            (status == 500 || (502 <= status && status < 504))) {
          return response.stream.drain().then((_) {
            // Delay the next attempt. Default backoff function is exponential.
            int failedAttemts = _options.numberOfAttempts - attemptsLeft;
            var duration = _options.backoffFunction(failedAttemts);
            if (duration == null) {
              throw new common_external.DetailedApiRequestError(
                  status,
                  'Resumable upload: Uploading a chunk resulted in status '
                  '$status. Maximum number of retries reached.');
            }

            return new Future.delayed(duration).then((_) {
              return tryUpload(attemptsLeft - 1);
            });
          });
        } else if (!lastChunk && status != 308) {
            return response.stream.drain().then((_) {
              throw new common_external.DetailedApiRequestError(
                  status,
                  'Resumable upload: Uploading a chunk resulted in status '
                  '$status instead of 308.');
            });
        } else if (lastChunk && status != 201 && status != 200) {
          return response.stream.drain().then((_) {
            throw new common_external.DetailedApiRequestError(
                status,
                'Resumable upload: Uploading a chunk resulted in status '
                '$status instead of 200 or 201.');
          });
        } else {
          return response;
        }
      });
    }

    return tryUpload(_options.numberOfAttempts - 1);
  }

  /**
   * Uploads [length] bytes in [byteArrays] and ensures the upload was
   * successful.
   *
   * Content-Range: [start ... (start + length)[
   *
   * Returns the returned [http.StreamedResponse] or completes with an error if
   * the upload did not succeed. The response stream will not be listened to.
   */
  Future _uploadChunk(Uri uri, ResumableChunk chunk, {bool lastChunk: false}) {
    // If [uploadMedia.length] is null, we do not know the length.
    var mediaTotalLength = _uploadMedia.length;
    if (mediaTotalLength == null || lastChunk) {
      if (lastChunk) {
        mediaTotalLength = '${chunk.endOfChunk}';
      } else {
        mediaTotalLength = '*';
      }
    }

    var headers = {
        'user-agent' : USER_AGENT_STRING,
        'content-type' : _uploadMedia.contentType,
        'content-length' : '${chunk.length}',
        'content-range' :
            'bytes ${chunk.offset}-${chunk.endOfChunk - 1}/$mediaTotalLength',
    };

    var stream = _listOfBytes2Stream(chunk.byteArrays);
    var request = new RequestImpl('PUT', uri, stream);
    request.headers.addAll(headers);
    return _httpClient.send(request);
  }

  Stream<List<int>> _bytes2Stream(List<int> bytes) {
    var bodyController = new StreamController<List<int>>();
    if (bytes != null) {
      bodyController.add(bytes);
    }
    bodyController.close();
    return bodyController.stream;
  }

  Stream<List<int>> _listOfBytes2Stream(List<List<int>> listOfBytes) {
    var controller = new StreamController();
    for (var array in listOfBytes) {
      controller.add(array);
    }
    controller.close();
    return controller.stream;
  }
}


/**
 * Represents a stack of [ResumableChunk]s.
 */
class ChunkStack {
  final int _chunkSize;
  final List<ResumableChunk> _chunkStack = [];

  // Currently accumulated data.
  List<List<int>> _byteArrays = [];
  int _length = 0;
  int _offset = 0;

  bool _finalized = false;

  ChunkStack(this._chunkSize);

  /**
   * Whether data for a not-yet-finished [ResumableChunk] is present. A call to
   * `finalize` will create a [ResumableChunk] of this data.
   */
  bool get hasPartialChunk => _length > 0;

  /**
   * The number of chunks in this [ChunkStack].
   */
  int get length => _chunkStack.length;

  /**
   * The total number of bytes which have been converted to [ResumableChunk]s.
   * Can only be called once this [ChunkStack] has been finalized.
   */
  int get totalByteLength {
    if (!_finalized) {
      throw new StateError('ChunkStack has not been finalized yet.');
    }

    return _offset;
  }

  /**
   * Returns the chunks [from] ... [to] and deletes it from the stack.
   */
  List<ResumableChunk> removeSublist(int from, int to) {
    var sublist = _chunkStack.sublist(from, to);
    _chunkStack.removeRange(from, to);
    return sublist;
  }

  /**
   * Adds [bytes] to the buffer. If the buffer is larger than the given chunk
   * size a new [ResumableChunk] will be created.
   */
  void addBytes(List<int> bytes) {
    if (_finalized) {
      throw new StateError('ChunkStack has already been finalized.');
    }

    var remaining = _chunkSize - _length;

    if (bytes.length >= remaining) {
      var left = bytes.sublist(0, remaining);
      var right = bytes.sublist(remaining);

      _byteArrays.add(left);
      _length += left.length;

      _chunkStack.add(new ResumableChunk(_byteArrays, _offset, _length));

      _byteArrays = [];
      _offset += _length;
      _length = 0;

      addBytes(right);
    } else if (bytes.length > 0) {
      _byteArrays.add(bytes);
      _length += bytes.length;
    }
  }

  /**
   * Finalizes this [ChunkStack] and creates the last chunk (may have less bytes
   * than the chunk size, but not zero).
   */
  void finalize() {
    if (_finalized) {
      throw new StateError('ChunkStack has already been finalized.');
    }
    _finalized = true;

    if (_length > 0) {
      _chunkStack.add(new ResumableChunk(_byteArrays, _offset, _length));
      _offset += _length;
    }
  }
}


/**
 * Represents a chunk of data that will be transferred in one http request.
 */
class ResumableChunk {
  final List<List<int>> byteArrays;
  final int offset;
  final int length;

  /**
   * Index of the next byte after this chunk.
   */
  int get endOfChunk => offset + length;

  ResumableChunk(this.byteArrays, this.offset, this.length);
}

class RequestImpl extends http.BaseRequest {
  final Stream<List<int>> _stream;

  RequestImpl(String method, Uri url, [Stream<List<int>> stream])
      : _stream = stream == null ? new Stream.fromIterable([]) : stream,
        super(method, url);

  http.ByteStream finalize() {
    super.finalize();
    return new http.ByteStream(_stream);
  }
}


class Escaper {
  // Character class definitions from RFC 6570
  // (see http://tools.ietf.org/html/rfc6570)
  // ALPHA          =  %x41-5A / %x61-7A   ; A-Z / a-z
  // DIGIT          =  %x30-39             ; 0
  // HEXDIG         =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
  // pct-encoded    =  "%" HEXDIG HEXDIG
  // unreserved     =  ALPHA / DIGIT / "-" / "." / "_" / "~"
  // reserved       =  gen-delims / sub-delims
  // gen-delims     =  ":" / "/" / "?" / "#" / "[" / "]" / "@"
  // sub-delims     =  "!" / "$" / "&" / "'" / "(" / ")"
  //                /  "*" / "+" / "," / ";" / "="

  // NOTE: Uri.encodeQueryComponent() does the following:
  // ...
  // Then the resulting bytes are "percent-encoded". This transforms spaces
  // (U+0020) to a plus sign ('+') and all bytes that are not the ASCII decimal
  // digits, letters or one of '-._~' are written as a percent sign '%'
  // followed by the two-digit hexadecimal representation of the byte.
  // ...

  // NOTE: Uri.encodeFull() does the following:
  // ...
  // All characters except uppercase and lowercase letters, digits and the
  // characters !#$&'()*+,-./:;=?@_~ are percent-encoded.
  // ...

  static String ecapeVariableReserved(String name) {
    // ... perform variable expansion, as defined in Section 3.2.1, with the
    // allowed characters being those in the set
    // (unreserved / reserved / pct-encoded)

    // NOTE: The chracters [ and ] need (according to URI Template spec) not be
    // percent encoded. The dart implementation does percent-encode [ and ].
    // This gives us in effect a conservative encoding, since the server side
    // must interpret percent-encoded parts anyway due to arbitrary unicode.

    // NOTE: This is broken in the discovery protocol. It allows ? and & to be
    // expanded via URI Templates which may generate completely bogus URIs.
    // TODO/FIXME: Should we change this to _encodeUnreserved() as well
    // (disadvantage, slashes get encoded at this point)?
    return Uri.encodeFull(name);
  }

  static String ecapePathComponent(String name) {
    // For each defined variable in the variable-list, append "/" to the
    // result string and then perform variable expansion, as defined in
    // Section 3.2.1, with the allowed characters being those in the
    // *unreserved set*.
    return _encodeUnreserved(name);
  }

  static String ecapeVariable(String name) {
    // ... perform variable expansion, as defined in Section 3.2.1, with the
    // allowed characters being those in the *unreserved set*.
    return _encodeUnreserved(name);
  }

  static String escapeQueryComponent(String name) {
    // This method will not be used by UriTemplate, but rather for encoding
    // normal query name/value pairs.

    // NOTE: For safety reasons we use '%20' instead of '+' here as well.
    // TODO/FIXME: Should we do this?
    return _encodeUnreserved(name);
  }

  static String _encodeUnreserved(String name) {
    // The only difference between dart's [Uri.encodeQueryComponent] and the
    // encoding defined by RFC 6570 for the above-defined unreserved character
    // set is the encoding of space.
    // Dart's Uri class will convert spaces to '+' which we replace by '%20'.
    return Uri.encodeQueryComponent(name).replaceAll('+', '%20');
  }
}


Future<http.StreamedResponse> _validateResponse(
    http.StreamedResponse response) {
  var statusCode = response.statusCode;

  // TODO: We assume that status codes between [200..400[ are OK.
  // Can we assume this?
  if (statusCode < 200 || statusCode >= 400) {
    throwGeneralError() {
      throw new common_external.ApiRequestError(
          'No error details. Http status was: ${response.statusCode}.');
    }

    // Some error happened, try to decode the response and fetch the error.
    Stream<String> stringStream = _decodeStreamAsText(response);
    if (stringStream != null) {
      return stringStream.transform(JSON.decoder).first.then((json) {
        if (json is Map && json['error'] is Map) {
          var error = json['error'];
          var code = error['code'];
          var message = error['message'];
          throw new common_external.DetailedApiRequestError(code, message);
        } else {
          throwGeneralError();
        }
      });
    } else {
      throwGeneralError();
    }
  }

  return new Future.value(response);
}


Stream<String> _decodeStreamAsText(http.StreamedResponse response) {
  // TODO: Correctly handle the response content-types, using correct
  // decoder.
  // Currently we assume that the api endpoint is responding with json
  // encoded in UTF8.
  String contentType = response.headers['content-type'];
  if (contentType != null &&
      contentType.toLowerCase().startsWith('application/json')) {
    return response.stream.transform(new Utf8Decoder(allowMalformed: true));
  } else {
    return null;
  }
}

Map mapMap(Map source, [Object convert(Object source) = null]) {
  assert(source != null);
  var result = new collection.LinkedHashMap();
  source.forEach((String key, value) {
    assert(key != null);
    if(convert == null) {
      result[key] = value;
    } else {
      result[key] = convert(value);
    }
  });
  return result;
}

