// Copyright (c) 2017, 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.

part of sync.http;

/// A simple synchronous HTTP client.
///
/// This is a two-step process. When a [SyncHttpClientRequest] is returned the
/// underlying network connection has been established, but no data has yet been
/// sent. The HTTP headers and body can be set on the request, and close is
/// called to send it to the server and get the [SyncHttpClientResponse].
abstract class SyncHttpClient {
  /// Send a GET request to the provided URL.
  static SyncHttpClientRequest getUrl(Uri uri) =>
      new SyncHttpClientRequest._('GET', uri, false);

  /// Send a POST request to the provided URL.
  static SyncHttpClientRequest postUrl(uri) =>
      new SyncHttpClientRequest._('POST', uri, true);

  /// Send a DELETE request to the provided URL.
  static SyncHttpClientRequest deleteUrl(uri) =>
      new SyncHttpClientRequest._('DELETE', uri, false);

  /// Send a PUT request to the provided URL.
  static SyncHttpClientRequest putUrl(uri) =>
      new SyncHttpClientRequest._('PUT', uri, true);
}

/// HTTP request for a synchronous client connection.
class SyncHttpClientRequest {
  static const String _protocolVersion = '1.1';

  /// The length of the request body. Is set to null when no body exists.
  int get contentLength => hasBody ? _body.length : null;

  HttpHeaders _headers;

  /// The headers associated with the HTTP request.
  HttpHeaders get headers {
    if (_headers == null) {
      _headers = new _SyncHttpClientRequestHeaders(this);
    }
    return _headers;
  }

  /// The type of HTTP request being made.
  final String method;

  /// The Uri the HTTP request will be sent to.
  final Uri uri;

  /// The default encoding for the HTTP request (UTF8).
  final Encoding encoding = UTF8;

  /// The body of the HTTP request. This can be empty if there is no body
  /// associated with the request.
  final BytesBuilder _body;

  /// The synchronous socket used to initiate the HTTP request.
  final RawSynchronousSocket _socket;

  SyncHttpClientRequest._(this.method, Uri uri, bool body)
      : this.uri = uri,
        this._body = body ? new BytesBuilder() : null,
        this._socket = RawSynchronousSocket.connectSync(uri.host, uri.port);

  /// Write content into the body of the HTTP request.
  void write(Object obj) {
    if (hasBody) {
      _body.add(encoding.encoder.convert(obj.toString()));
    } else {
      throw new StateError('write not allowed for method $method');
    }
  }

  /// Specifies whether or not the HTTP request has a body.
  bool get hasBody => _body != null;

  /// Send the HTTP request and get the response.
  SyncHttpClientResponse close() {
    StringBuffer buffer = new StringBuffer();
    buffer.write('$method ${uri.path} HTTP/$_protocolVersion\r\n');
    headers.forEach((name, values) {
      values.forEach((value) {
        buffer.write('$name: $value\r\n');
      });
    });
    buffer.write('\r\n');
    if (hasBody) {
      buffer.write(new String.fromCharCodes(_body.takeBytes()));
    }
    _socket.writeFromSync(buffer.toString().codeUnits);
    return new SyncHttpClientResponse(_socket);
  }
}

class _SyncHttpClientRequestHeaders implements HttpHeaders {
  Map<String, List> _headers = <String, List<String>>{};

  final SyncHttpClientRequest _request;
  ContentType contentType;

  _SyncHttpClientRequestHeaders(this._request);

  @override
  List<String> operator [](String name) {
    switch (name) {
      case HttpHeaders.ACCEPT_CHARSET:
        return ['utf-8'];
      case HttpHeaders.ACCEPT_ENCODING:
        return ['identity'];
      case HttpHeaders.CONNECTION:
        return ['close'];
      case HttpHeaders.CONTENT_LENGTH:
        if (!_request.hasBody) {
          return null;
        }
        return [contentLength.toString()];
      case HttpHeaders.CONTENT_TYPE:
        if (contentType == null) {
          return null;
        }
        return [contentType.toString()];
      case HttpHeaders.HOST:
        return ['$host:$port'];
      default:
        var values = _headers[name];
        if (values == null || values.isEmpty) {
          return null;
        }
        return values.map((e) => e.toString()).toList(growable: false);
    }
  }

  /// Add [value] to the list of values associated with header [name].
  @override
  void add(String name, Object value) {
    switch (name) {
      case HttpHeaders.ACCEPT_CHARSET:
      case HttpHeaders.ACCEPT_ENCODING:
      case HttpHeaders.CONNECTION:
      case HttpHeaders.CONTENT_LENGTH:
      case HttpHeaders.DATE:
      case HttpHeaders.EXPIRES:
      case HttpHeaders.IF_MODIFIED_SINCE:
      case HttpHeaders.HOST:
        throw new UnsupportedError('Unsupported or immutable property: $name');
      case HttpHeaders.CONTENT_TYPE:
        contentType = value;
        break;
      default:
        if (_headers[name] == null) {
          _headers[name] = [];
        }
        _headers[name].add(value);
    }
  }

  /// Remove [value] from the list associated with header [name].
  @override
  void remove(String name, Object value) {
    switch (name) {
      case HttpHeaders.ACCEPT_CHARSET:
      case HttpHeaders.ACCEPT_ENCODING:
      case HttpHeaders.CONNECTION:
      case HttpHeaders.CONTENT_LENGTH:
      case HttpHeaders.DATE:
      case HttpHeaders.EXPIRES:
      case HttpHeaders.IF_MODIFIED_SINCE:
      case HttpHeaders.HOST:
        throw new UnsupportedError('Unsupported or immutable property: $name');
      case HttpHeaders.CONTENT_TYPE:
        if (contentType == value) {
          contentType = null;
        }
        break;
      default:
        if (_headers[name] != null) {
          _headers[name].remove(value);
          if (_headers[name].isEmpty) {
            _headers.remove(name);
          }
        }
    }
  }

  /// Remove all headers associated with key [name].
  @override
  void removeAll(String name) {
    switch (name) {
      case HttpHeaders.ACCEPT_CHARSET:
      case HttpHeaders.ACCEPT_ENCODING:
      case HttpHeaders.CONNECTION:
      case HttpHeaders.CONTENT_LENGTH:
      case HttpHeaders.DATE:
      case HttpHeaders.EXPIRES:
      case HttpHeaders.IF_MODIFIED_SINCE:
      case HttpHeaders.HOST:
        throw new UnsupportedError('Unsupported or immutable property: $name');
      case HttpHeaders.CONTENT_TYPE:
        contentType = null;
        break;
      default:
        _headers.remove(name);
    }
  }

  /// Replace values associated with key [name] with [value].
  @override
  void set(String name, Object value) {
    removeAll(name);
    add(name, value);
  }

  /// Returns the values associated with key [name], if it exists, otherwise
  /// returns null.
  @override
  String value(String name) {
    var val = this[name];
    if (val == null || val.isEmpty) {
      return null;
    } else if (val.length == 1) {
      return val[0];
    } else {
      throw new HttpException('header $name has more than one value');
    }
  }

  /// Iterates over all header key-value pairs and applies [f].
  @override
  void forEach(void f(String name, List<String> values)) {
    var forEachFunc = (String name) {
      var values = this[name];
      if (values != null && values.isNotEmpty) {
        f(name, values);
      }
    };

    [
      HttpHeaders.ACCEPT_CHARSET,
      HttpHeaders.ACCEPT_ENCODING,
      HttpHeaders.CONNECTION,
      HttpHeaders.CONTENT_LENGTH,
      HttpHeaders.CONTENT_TYPE,
      HttpHeaders.HOST
    ].forEach(forEachFunc);
    _headers.keys.forEach(forEachFunc);
  }

  @override
  bool get chunkedTransferEncoding => null;

  @override
  void set chunkedTransferEncoding(bool _chunkedTransferEncoding) {
    throw new UnsupportedError('chunked transfer is unsupported');
  }

  @override
  int get contentLength => _request.contentLength;

  @override
  void set contentLength(int _contentLength) {
    throw new UnsupportedError('content length is automatically set');
  }

  @override
  void set date(DateTime _date) {
    throw new UnsupportedError('date is unsupported');
  }

  @override
  DateTime get date => null;

  @override
  void set expires(DateTime _expires) {
    throw new UnsupportedError('expires is unsupported');
  }

  @override
  DateTime get expires => null;

  @override
  void set host(String _host) {
    throw new UnsupportedError('host is automatically set');
  }

  @override
  String get host => _request.uri.host;

  @override
  DateTime get ifModifiedSince => null;

  @override
  void set ifModifiedSince(DateTime _ifModifiedSince) {
    throw new UnsupportedError('if modified since is unsupported');
  }

  @override
  void noFolding(String name) {
    throw new UnsupportedError('no folding is unsupported');
  }

  @override
  bool get persistentConnection => false;

  @override
  void set persistentConnection(bool _persistentConnection) {
    throw new UnsupportedError('persistence connections are unsupported');
  }

  @override
  void set port(int _port) {
    throw new UnsupportedError('port is automatically set');
  }

  @override
  int get port => _request.uri.port;

  /// Clear all header key-value pairs.
  @override
  void clear() {
    contentType = null;
    _headers.clear();
  }
}

/// HTTP response for a client connection.
class SyncHttpClientResponse {
  /// The length of the body associated with the HTTP response.
  int get contentLength => headers.contentLength;

  /// The headers associated with the HTTP response.
  final HttpHeaders headers;

  /// A short textual description of the status code associated with the HTTP
  /// response.
  final String reasonPhrase;

  /// The resulting HTTP status code associated with the HTTP response.
  final int statusCode;

  /// The body of the HTTP response.
  final String body;

  /// Creates an instance of [SyncHttpClientResponse] that contains the response
  /// sent by the HTTP server over [socket].
  factory SyncHttpClientResponse(RawSynchronousSocket socket) {
    int statusCode;
    String reasonPhrase;
    StringBuffer body = new StringBuffer();
    Map<String, List<String>> headers = {};

    bool inHeader = false;
    bool inBody = false;
    int contentLength = 0;
    int contentRead = 0;

    void processLine(String line, int bytesRead, _LineDecoder decoder) {
      if (inBody) {
        body.write(line);
        contentRead += bytesRead;
      } else if (inHeader) {
        if (line.trim().isEmpty) {
          inBody = true;
          if (contentLength > 0) {
            decoder.expectedByteCount = contentLength;
          }
          return;
        }
        int separator = line.indexOf(':');
        String name = line.substring(0, separator).toLowerCase().trim();
        String value = line.substring(separator + 1).trim();
        if (name == HttpHeaders.TRANSFER_ENCODING &&
            value.toLowerCase() != 'identity') {
          throw new UnsupportedError(
              'only identity transfer encoding is accepted');
        }
        if (name == HttpHeaders.CONTENT_LENGTH) {
          contentLength = int.parse(value);
        }
        if (!headers.containsKey(name)) {
          headers[name] = [];
        }
        headers[name].add(value);
      } else if (line.startsWith('HTTP/1.1') || line.startsWith('HTTP/1.0')) {
        statusCode = int
            .parse(line.substring('HTTP/1.x '.length, 'HTTP/1.x xxx'.length));
        reasonPhrase = line.substring('HTTP/1.x xxx '.length);
        inHeader = true;
      } else {
        throw new UnsupportedError('unsupported http response format');
      }
    }

    var lineDecoder = new _LineDecoder.withCallback(processLine);

    try {
      while (!inHeader ||
          !inBody ||
          ((contentRead + lineDecoder.bufferedBytes) < contentLength)) {
        var bytes = socket.readSync(1024);

        if (bytes == null || bytes.length == 0) {
          break;
        }
        lineDecoder.add(bytes);
      }
    } finally {
      try {
        lineDecoder.close();
      } finally {
        socket.closeSync();
      }
    }

    return new SyncHttpClientResponse._(
        reasonPhrase: reasonPhrase,
        statusCode: statusCode,
        body: body.toString(),
        headers: headers);
  }

  SyncHttpClientResponse._(
      {this.reasonPhrase, this.statusCode, this.body, headers})
      : this.headers = new _SyncHttpClientResponseHeaders(headers);
}

class _SyncHttpClientResponseHeaders implements HttpHeaders {
  final Map<String, List<String>> _headers;

  _SyncHttpClientResponseHeaders(this._headers);

  @override
  List<String> operator [](String name) => _headers[name];

  @override
  void add(String name, Object value) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  bool get chunkedTransferEncoding => null;

  @override
  void set chunkedTransferEncoding(bool _chunkedTransferEncoding) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  int get contentLength {
    String val = value(HttpHeaders.CONTENT_LENGTH);
    if (val != null) {
      return int.parse(val, onError: (_) => null);
    }
    return null;
  }

  @override
  void set contentLength(int _contentLength) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  ContentType get contentType {
    var val = value(HttpHeaders.CONTENT_TYPE);
    if (val != null) {
      return ContentType.parse(val);
    }
    return null;
  }

  @override
  void set contentType(ContentType _contentType) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  void set date(DateTime _date) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  DateTime get date {
    var val = value(HttpHeaders.DATE);
    if (val != null) {
      return DateTime.parse(val);
    }
    return null;
  }

  @override
  void set expires(DateTime _expires) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  DateTime get expires {
    var val = value(HttpHeaders.EXPIRES);
    if (val != null) {
      return DateTime.parse(val);
    }
    return null;
  }

  @override
  void forEach(void f(String name, List<String> values)) => _headers.forEach(f);

  @override
  void set host(String _host) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  String get host {
    var val = value(HttpHeaders.HOST);
    if (val != null) {
      return Uri.parse(val).host;
    }
    return null;
  }

  @override
  DateTime get ifModifiedSince {
    var val = value(HttpHeaders.IF_MODIFIED_SINCE);
    if (val != null) {
      return DateTime.parse(val);
    }
    return null;
  }

  @override
  void set ifModifiedSince(DateTime _ifModifiedSince) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  void noFolding(String name) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  bool get persistentConnection => false;

  @override
  void set persistentConnection(bool _persistentConnection) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  void set port(int _port) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  int get port {
    var val = value(HttpHeaders.HOST);
    if (val != null) {
      return Uri.parse(val).port;
    }
    return null;
  }

  @override
  void remove(String name, Object value) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  void removeAll(String name) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  void set(String name, Object value) {
    throw new UnsupportedError('Response headers are immutable');
  }

  @override
  String value(String name) {
    var val = this[name];
    if (val == null || val.isEmpty) {
      return null;
    } else if (val.length == 1) {
      return val[0];
    } else {
      throw new HttpException('header $name has more than one value');
    }
  }

  @override
  void clear() {
    throw new UnsupportedError('Response headers are immutable');
  }
}
