// Copyright (c) 2013, 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 request;

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'base_request.dart';
import 'byte_stream.dart';
import 'utils.dart';

/// An HTTP request where the entire request body is known in advance.
class Request extends BaseRequest {
  /// The size of the request body, in bytes. This is calculated from
  /// [bodyBytes].
  ///
  /// The content length cannot be set for [Request], since it's automatically
  /// calculated from [bodyBytes].
  int get contentLength => bodyBytes.length;

  set contentLength(int value) {
    throw new UnsupportedError("Cannot set the contentLength property of "
        "non-streaming Request objects.");
  }

  /// The default encoding to use when converting between [bodyBytes] and
  /// [body]. This is only used if [encoding] hasn't been manually set and if
  /// the content-type header has no encoding information.
  Encoding _defaultEncoding;

  /// The encoding used for the request. This encoding is used when converting
  /// between [bodyBytes] and [body].
  ///
  /// If the request has a `Content-Type` header and that header has a `charset`
  /// parameter, that parameter's value is used as the encoding. Otherwise, if
  /// [encoding] has been set manually, that encoding is used. If that hasn't
  /// been set either, this defaults to [Encoding.UTF_8].
  ///
  /// If the `charset` parameter's value is not a known [Encoding], reading this
  /// will throw a [FormatException].
  ///
  /// If the request has a `Content-Type` header, setting this will set the
  /// charset parameter on that header.
  Encoding get encoding {
    if (_contentType == null || _contentType.charset == null) {
      return _defaultEncoding;
    }
    return requiredEncodingForCharset(_contentType.charset);
  }

  set encoding(Encoding value) {
    _checkFinalized();
    _defaultEncoding = value;
    var contentType = _contentType;
    if (contentType != null) {
      contentType = new ContentType(contentType.primaryType,
                                    contentType.subType,
                                    charset: value.name,
                                    parameters: contentType.parameters);
      _contentType = contentType;
    }
  }

  // TODO(nweiz): make this return a read-only view
  /// The bytes comprising the body of the request. This is converted to and
  /// from [body] using [encoding].
  ///
  /// This list should only be set, not be modified in place.
  Uint8List get bodyBytes => _bodyBytes;
  Uint8List _bodyBytes;

  set bodyBytes(List<int> value) {
    _checkFinalized();
    _bodyBytes = toUint8List(value);
  }

  /// The body of the request as a string. This is converted to and from
  /// [bodyBytes] using [encoding].
  ///
  /// When this is set, if the request does not yet have a `Content-Type`
  /// header, one will be added with the type `text/plain`. Then the `charset`
  /// parameter of the `Content-Type` header (whether new or pre-existing) will
  /// be set to [encoding] if it wasn't already set.
  String get body => decodeString(bodyBytes, encoding);

  set body(String value) {
    bodyBytes = encodeString(value, encoding);
    var contentType = _contentType;
    if (contentType == null) {
      contentType = new ContentType("text", "plain", charset: encoding.name);
    } else if (contentType.charset == null) {
      contentType = new ContentType(contentType.primaryType,
                                    contentType.subType,
                                    charset: encoding.name,
                                    parameters: contentType.parameters);
    }
    _contentType = contentType;
  }

  /// The form-encoded fields in the body of the request as a map from field
  /// names to values. The form-encoded body is converted to and from
  /// [bodyBytes] using [encoding] (in the same way as [body]).
  ///
  /// If the request doesn't have a `Content-Type` header of
  /// `application/x-www-form-urlencoded`, reading this will throw a
  /// [StateError].
  ///
  /// If the request has a `Content-Type` header with a type other than
  /// `application/x-www-form-urlencoded`, setting this will throw a
  /// [StateError]. Otherwise, the content type will be set to
  /// `application/x-www-form-urlencoded`.
  ///
  /// This map should only be set, not modified in place.
  Map<String, String> get bodyFields {
    if (_contentType == null ||
        _contentType.value != "application/x-www-form-urlencoded") {
      throw new StateError('Cannot access the body fields of a Request without '
          'content-type "application/x-www-form-urlencoded".');
    }

    return queryToMap(body);
  }

  set bodyFields(Map<String, String> fields) {
    if (_contentType == null) {
      _contentType = new ContentType("application", "x-www-form-urlencoded");
    } else if (_contentType.value != "application/x-www-form-urlencoded") {
      throw new StateError('Cannot set the body fields of a Request with '
          'content-type "${_contentType.value}".');
    }

    this.body = mapToQuery(fields);
  }

  /// Creates a new HTTP request.
  Request(String method, Uri url)
    : super(method, url),
      _defaultEncoding = Encoding.UTF_8,
      _bodyBytes = new Uint8List(0);

  /// Freezes all mutable fields and returns a single-subscription [ByteStream]
  /// containing the request body.
  ByteStream finalize() {
    super.finalize();
    return new ByteStream.fromBytes(bodyBytes);
  }

  /// The `Content-Type` header of the request (if it exists) as a
  /// [ContentType].
  ContentType get _contentType {
    var contentType = headers[HttpHeaders.CONTENT_TYPE];
    if (contentType == null) return null;
    return ContentType.parse(contentType);
  }

  set _contentType(ContentType value) {
    headers[HttpHeaders.CONTENT_TYPE] = value.toString();
  }

  /// Throw an error if this request has been finalized.
  void _checkFinalized() {
    if (!finalized) return;
    throw new StateError("Can't modify a finalized Request.");
  }
}
