// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @dart = 2.8

import 'dart:async';
import 'dart:convert';

import 'dart:io';

import 'package:flutter_tools/src/base/io.dart';

/// The HTTP verb for a [FakeRequest].
enum HttpMethod {
  get,
  put,
  delete,
  post,
  patch,
  head,
}

HttpMethod _fromMethodString(String value) {
  final String name = value.toLowerCase();
  switch (name) {
    case 'get':
      return HttpMethod.get;
    case 'put':
      return HttpMethod.put;
    case 'delete':
      return HttpMethod.delete;
    case 'post':
      return HttpMethod.post;
    case 'patch':
      return HttpMethod.patch;
    case 'head':
      return HttpMethod.head;
    default:
      throw StateError('Unrecognized HTTP method $value');
  }
}

String _toMethodString(HttpMethod method) {
  switch (method) {
    case HttpMethod.get:
      return 'GET';
    case HttpMethod.put:
      return 'PUT';
    case HttpMethod.delete:
      return 'DELETE';
    case HttpMethod.post:
      return 'POST';
    case HttpMethod.patch:
      return 'PATCH';
    case HttpMethod.head:
      return 'HEAD';
  }
  assert(false);
  return null;
}

/// Override the creation of all [HttpClient] objects with a zone injection.
///
/// This should only be used when the http client cannot be set directly, such as
/// when testing `package:http` code.
Future<void> overrideHttpClients(Future<void> Function() callback,  FakeHttpClient httpClient) async {
  final HttpOverrides overrides = _FakeHttpClientOverrides(httpClient);
  await HttpOverrides.runWithHttpOverrides(callback, overrides);
}

class _FakeHttpClientOverrides extends HttpOverrides {
  _FakeHttpClientOverrides(this.httpClient);

  final FakeHttpClient httpClient;

  @override
  HttpClient createHttpClient(SecurityContext context) {
    return httpClient;
  }
}

/// Create a fake request that configures the [FakeHttpClient] to respond
/// with the provided [response].
///
/// By default, returns a response with a 200 OK status code and an
/// empty response. If [responseError] is non-null, will throw this instead
/// of returning the response when closing the request.
class FakeRequest {
  const FakeRequest(this.uri, {
    this.method = HttpMethod.get,
    this.response = FakeResponse.empty,
    this.responseError,
  });

  final Uri uri;
  final HttpMethod method;
  final FakeResponse response;
  final dynamic responseError;

  @override
  String toString() => 'Request{${_toMethodString(method)}, $uri}';
}

/// The response the server will create for a given [FakeRequest].
class FakeResponse {
  const FakeResponse({
    this.statusCode = HttpStatus.ok,
    this.body = const <int>[],
    this.headers = const <String, List<String>>{},
  });

  static const FakeResponse empty = FakeResponse();

  final int statusCode;
  final List<int> body;
  final Map<String, List<String>> headers;
}

/// A fake implementation of the HttpClient used for testing.
///
/// This does not fully implement the HttpClient. If an additional method
/// is actually needed by the test script, then it should be added here
/// instead of in another fake.
class FakeHttpClient implements HttpClient {
  /// Creates an HTTP client that responses to each provided
  /// fake request with the provided fake response.
  ///
  /// This does not enforce any order on the requests, but if multiple
  /// requests match then the first will be selected;
  FakeHttpClient.list(List<FakeRequest> requests)
    : _requests = requests.toList();

  /// Creates an HTTP client that always returns an empty 200 request.
  FakeHttpClient.any() : _any = true, _requests = <FakeRequest>[];

  bool _any = false;
  final List<FakeRequest> _requests;

  @override
  bool autoUncompress;

  @override
  Duration connectionTimeout;

  @override
  Duration idleTimeout;

  @override
  int maxConnectionsPerHost;

  @override
  String userAgent;

  @override
  void addCredentials(Uri url, String realm, HttpClientCredentials credentials) {
    throw UnimplementedError();
  }

  @override
  void addProxyCredentials(String host, int port, String realm, HttpClientCredentials credentials) {
    throw UnimplementedError();
  }

  @override
  set authenticate(Future<bool> Function(Uri url, String scheme, String realm) f) {
    throw UnimplementedError();
  }

  @override
  set authenticateProxy(Future<bool> Function(String host, int port, String scheme, String realm) f) {
    throw UnimplementedError();
  }

  @override
  set badCertificateCallback(bool Function(X509Certificate cert, String host, int port) callback) {
    throw UnimplementedError();
  }

  @override
  void close({bool force = false}) { }

  @override
  Future<HttpClientRequest> delete(String host, int port, String path) {
    final Uri uri = Uri(host: host, port: port, path: path);
    return deleteUrl(uri);
  }

  @override
  Future<HttpClientRequest> deleteUrl(Uri url) async {
    return _findRequest(HttpMethod.delete, url);
  }

  @override
  set findProxy(String Function(Uri url) f) { }

  @override
  Future<HttpClientRequest> get(String host, int port, String path) {
    final Uri uri = Uri(host: host, port: port, path: path);
    return getUrl(uri);
  }

  @override
  Future<HttpClientRequest> getUrl(Uri url) async {
    return _findRequest(HttpMethod.get, url);
  }

  @override
  Future<HttpClientRequest> head(String host, int port, String path) {
    final Uri uri = Uri(host: host, port: port, path: path);
    return headUrl(uri);
  }

  @override
  Future<HttpClientRequest> headUrl(Uri url) async {
    return _findRequest(HttpMethod.head, url);
  }

  @override
  Future<HttpClientRequest> open(String method, String host, int port, String path) {
    final Uri uri = Uri(host: host, port: port, path: path);
    return openUrl(method, uri);
  }

  @override
  Future<HttpClientRequest> openUrl(String method, Uri url) async {
    return _findRequest(_fromMethodString(method), url);
  }

  @override
  Future<HttpClientRequest> patch(String host, int port, String path) {
    final Uri uri = Uri(host: host, port: port, path: path);
    return patchUrl(uri);
  }

  @override
  Future<HttpClientRequest> patchUrl(Uri url) async {
    return _findRequest(HttpMethod.patch, url);
  }

  @override
  Future<HttpClientRequest> post(String host, int port, String path) {
    final Uri uri = Uri(host: host, port: port, path: path);
    return postUrl(uri);
  }

  @override
  Future<HttpClientRequest> postUrl(Uri url) async {
    return _findRequest(HttpMethod.post, url);
  }

  @override
  Future<HttpClientRequest> put(String host, int port, String path) {
    final Uri uri = Uri(host: host, port: port, path: path);
    return putUrl(uri);
  }

  @override
  Future<HttpClientRequest> putUrl(Uri url) async {
    return _findRequest(HttpMethod.put, url);
  }

  int _requestCount = 0;

  _FakeHttpClientRequest _findRequest(HttpMethod method, Uri uri) {
    // Ensure the fake client throws similar errors to the real client.
    if (uri.host.isEmpty) {
      throw ArgumentError('No host specified in URI $uri');
    } else if (uri.scheme != 'http' && uri.scheme != 'https') {
      throw ArgumentError("Unsupported scheme '${uri.scheme}' in URI $uri");
    }
    final String methodString = _toMethodString(method);
    if (_any) {
      return _FakeHttpClientRequest(
        FakeResponse.empty,
        uri,
        methodString,
        null,
      );
    }
    FakeRequest matchedRequest;
    for (final FakeRequest request in _requests) {
      if (request.method == method && request.uri.toString() == uri.toString()) {
        matchedRequest = request;
        break;
      }
    }
    if (matchedRequest == null) {
      throw StateError(
        'Unexpected request for $method to $uri after $_requestCount requests.\n'
        'Pending requests: ${_requests.join(',')}'
      );
    }
    _requestCount += 1;
    _requests.remove(matchedRequest);
    return _FakeHttpClientRequest(
      matchedRequest.response,
      uri,
      methodString,
      matchedRequest.responseError,
    );
  }
}

class _FakeHttpClientRequest implements HttpClientRequest {
  _FakeHttpClientRequest(this._response, this._uri, this._method, this._responseError);

  final FakeResponse _response;
  final String _method;
  final Uri _uri;
  final dynamic _responseError;

  @override
  bool bufferOutput;

  @override
  int contentLength = 0;

  @override
  Encoding encoding;

  @override
  bool followRedirects;

  @override
  int maxRedirects;

  @override
  bool persistentConnection;

  @override
  void abort([Object exception, StackTrace stackTrace]) {
    throw UnimplementedError();
  }

  @override
  void add(List<int> data) { }

  @override
  void addError(Object error, [StackTrace stackTrace]) { }

  @override
  Future<void> addStream(Stream<List<int>> stream) async { }

  @override
  Future<HttpClientResponse> close() async {
    if (_responseError != null) {
      return Future<HttpClientResponse>.error(_responseError);
    }
    return _FakeHttpClientResponse(_response);
  }

  @override
  HttpConnectionInfo get connectionInfo => throw UnimplementedError();

  @override
  List<Cookie> get cookies => throw UnimplementedError();

  @override
  Future<HttpClientResponse> get done => throw UnimplementedError();

  @override
  Future<void> flush() async { }

  @override
  final HttpHeaders headers = _FakeHttpHeaders(<String, List<String>>{});

  @override
  String get method => _method;

  @override
  Uri get uri => _uri;

  @override
  void write(Object object) { }

  @override
  void writeAll(Iterable<dynamic> objects, [String separator = '']) { }

  @override
  void writeCharCode(int charCode) { }

  @override
  void writeln([Object object = '']) { }
}

class _FakeHttpClientResponse extends Stream<List<int>> implements HttpClientResponse {
  _FakeHttpClientResponse(this._response)
      : headers = _FakeHttpHeaders(Map<String, List<String>>.from(_response.headers));

  final FakeResponse _response;

  @override
  X509Certificate get certificate => throw UnimplementedError();

  @override
  HttpClientResponseCompressionState get compressionState => throw UnimplementedError();

  @override
  HttpConnectionInfo get connectionInfo => throw UnimplementedError();

  @override
  int get contentLength => _response.body.length;

  @override
  List<Cookie> get cookies => throw UnimplementedError();

  @override
  Future<Socket> detachSocket() {
    throw UnimplementedError();
  }

  @override
  final HttpHeaders headers;

  @override
  bool get isRedirect => throw UnimplementedError();

  @override
  StreamSubscription<List<int>> listen(
    void Function(List<int> event) onData, {
    Function onError,
    void Function() onDone,
    bool cancelOnError,
  }) {
    final Stream<List<int>> response = Stream<List<int>>.fromIterable(<List<int>>[
      _response.body,
    ]);
    return response.listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError);
  }

  @override
  bool get persistentConnection => throw UnimplementedError();

  @override
  String get reasonPhrase => 'OK';

  @override
  Future<HttpClientResponse> redirect([String method, Uri url, bool followLoops]) {
    throw UnimplementedError();
  }

  @override
  List<RedirectInfo> get redirects => throw UnimplementedError();

  @override
  int get statusCode => _response.statusCode;
}

class _FakeHttpHeaders extends HttpHeaders {
  _FakeHttpHeaders(this._backingData);

  final Map<String, List<String>> _backingData;

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

  @override
  void add(String name, Object value, {bool preserveHeaderCase = false}) {
    _backingData[name] ??= <String>[];
    _backingData[name].add(value.toString());
  }

  @override
  void clear() {
    _backingData.clear();
  }

  @override
  void forEach(void Function(String name, List<String> values) action) { }

  @override
  void noFolding(String name) {  }

  @override
  void remove(String name, Object value) {
    _backingData[name]?.remove(value.toString());
  }

  @override
  void removeAll(String name) {
    _backingData.remove(name);
  }

  @override
  void set(String name, Object value, {bool preserveHeaderCase = false}) {
    _backingData[name] = <String>[value.toString()];
  }

  @override
  String value(String name) {
    return _backingData[name]?.join('; ');
  }
}
