// Copyright (c) 2022, 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:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:async/async.dart';
import 'package:http/http.dart';
import 'package:http_profile/http_profile.dart';
import 'package:objective_c/objective_c.dart';

import 'cupertino_api.dart';

final _digitRegex = RegExp(r'^\d+$');

/// This class can be removed when `package:http` v2 is released.
class _StreamedResponseWithUrl extends StreamedResponse
    implements BaseResponseWithUrl {
  @override
  final Uri url;

  _StreamedResponseWithUrl(super.stream, super.statusCode,
      {required this.url,
      super.contentLength,
      super.request,
      super.headers,
      super.isRedirect,
      super.reasonPhrase});
}

class _TaskTracker {
  final responseCompleter = Completer<URLResponse>();
  final BaseRequest request;
  final responseController = StreamController<Uint8List>();
  final HttpClientRequestProfile? profile;
  int numRedirects = 0;
  Uri? lastUrl; // The last URL redirected to.

  _TaskTracker(this.request, this.profile);

  void close() {
    responseController.close();
  }
}

/// A HTTP [Client] based on the
/// [Foundation URL Loading System](https://developer.apple.com/documentation/foundation/url_loading_system).
///
/// For example:
/// ```
/// void main() async {
///   var client = CupertinoClient.defaultSessionConfiguration();
///   final response = await client.get(
///       Uri.https('www.googleapis.com', '/books/v1/volumes', {'q': '{http}'}));
///   if (response.statusCode != 200) {
///     throw HttpException('bad response: ${response.statusCode}');
///   }
///
///   final decodedResponse =
///       jsonDecode(utf8.decode(response.bodyBytes)) as Map;
///
///   final itemCount = decodedResponse['totalItems'];
///   print('Number of books about http: $itemCount.');
///   for (var i = 0; i < min(itemCount, 10); ++i) {
///     print(decodedResponse['items'][i]['volumeInfo']['title']);
///   }
/// }
/// ```
class CupertinoClient extends BaseClient {
  static final Map<URLSessionTask, _TaskTracker> _tasks = {};

  URLSession? _urlSession;

  CupertinoClient._(this._urlSession);

  String? _findReasonPhrase(int statusCode) {
    switch (statusCode) {
      case HttpStatus.continue_:
        return 'Continue';
      case HttpStatus.switchingProtocols:
        return 'Switching Protocols';
      case HttpStatus.ok:
        return 'OK';
      case HttpStatus.created:
        return 'Created';
      case HttpStatus.accepted:
        return 'Accepted';
      case HttpStatus.nonAuthoritativeInformation:
        return 'Non-Authoritative Information';
      case HttpStatus.noContent:
        return 'No Content';
      case HttpStatus.resetContent:
        return 'Reset Content';
      case HttpStatus.partialContent:
        return 'Partial Content';
      case HttpStatus.multipleChoices:
        return 'Multiple Choices';
      case HttpStatus.movedPermanently:
        return 'Moved Permanently';
      case HttpStatus.found:
        return 'Found';
      case HttpStatus.seeOther:
        return 'See Other';
      case HttpStatus.notModified:
        return 'Not Modified';
      case HttpStatus.useProxy:
        return 'Use Proxy';
      case HttpStatus.temporaryRedirect:
        return 'Temporary Redirect';
      case HttpStatus.badRequest:
        return 'Bad Request';
      case HttpStatus.unauthorized:
        return 'Unauthorized';
      case HttpStatus.paymentRequired:
        return 'Payment Required';
      case HttpStatus.forbidden:
        return 'Forbidden';
      case HttpStatus.notFound:
        return 'Not Found';
      case HttpStatus.methodNotAllowed:
        return 'Method Not Allowed';
      case HttpStatus.notAcceptable:
        return 'Not Acceptable';
      case HttpStatus.proxyAuthenticationRequired:
        return 'Proxy Authentication Required';
      case HttpStatus.requestTimeout:
        return 'Request Time-out';
      case HttpStatus.conflict:
        return 'Conflict';
      case HttpStatus.gone:
        return 'Gone';
      case HttpStatus.lengthRequired:
        return 'Length Required';
      case HttpStatus.preconditionFailed:
        return 'Precondition Failed';
      case HttpStatus.requestEntityTooLarge:
        return 'Request Entity Too Large';
      case HttpStatus.requestUriTooLong:
        return 'Request-URI Too Long';
      case HttpStatus.unsupportedMediaType:
        return 'Unsupported Media Type';
      case HttpStatus.requestedRangeNotSatisfiable:
        return 'Requested range not satisfiable';
      case HttpStatus.expectationFailed:
        return 'Expectation Failed';
      case HttpStatus.internalServerError:
        return 'Internal Server Error';
      case HttpStatus.notImplemented:
        return 'Not Implemented';
      case HttpStatus.badGateway:
        return 'Bad Gateway';
      case HttpStatus.serviceUnavailable:
        return 'Service Unavailable';
      case HttpStatus.gatewayTimeout:
        return 'Gateway Time-out';
      case HttpStatus.httpVersionNotSupported:
        return 'Http Version not supported';
      default:
        return null;
    }
  }

  static _TaskTracker _tracker(URLSessionTask task) => _tasks[task]!;

  static void _onComplete(
      URLSession session, URLSessionTask task, NSError? error) {
    final taskTracker = _tracker(task);
    if (error != null) {
      final exception = ClientException(
          error.localizedDescription.toString(), taskTracker.request.url);
      if (taskTracker.profile != null &&
          taskTracker.profile!.requestData.endTime == null) {
        // Error occurred during the request.
        taskTracker.profile!.requestData.closeWithError(exception.toString());
      } else {
        // Error occurred during the response.
        taskTracker.profile?.responseData.closeWithError(exception.toString());
      }
      if (taskTracker.responseCompleter.isCompleted) {
        taskTracker.responseController.addError(exception);
      } else {
        taskTracker.responseCompleter.completeError(exception);
      }
    } else {
      assert(taskTracker.profile == null ||
          taskTracker.profile!.requestData.endTime != null);

      taskTracker.profile?.responseData.close();
      if (!taskTracker.responseCompleter.isCompleted) {
        taskTracker.responseCompleter.completeError(
            StateError('task completed without an error or response'));
      }
    }
    taskTracker.close();
    _tasks.remove(task);
  }

  static void _onData(URLSession session, URLSessionTask task, NSData data) {
    final taskTracker = _tracker(task);
    taskTracker.responseController.add(data.toList());
    taskTracker.profile?.responseData.bodySink.add(data.toList());
  }

  static URLRequest? _onRedirect(URLSession session, URLSessionTask task,
      HTTPURLResponse response, URLRequest request) {
    final taskTracker = _tracker(task);
    ++taskTracker.numRedirects;
    if (taskTracker.request.followRedirects &&
        taskTracker.numRedirects <= taskTracker.request.maxRedirects) {
      taskTracker.profile?.responseData.addRedirect(HttpProfileRedirectData(
          statusCode: response.statusCode,
          method: request.httpMethod,
          location: request.url!.toString()));
      taskTracker.lastUrl = request.url;
      return request;
    }
    return null;
  }

  static NSURLSessionResponseDisposition _onResponse(
      URLSession session, URLSessionTask task, URLResponse response) {
    final taskTracker = _tracker(task);
    taskTracker.responseCompleter.complete(response);
    unawaited(taskTracker.profile?.requestData.close());

    return NSURLSessionResponseDisposition.NSURLSessionResponseAllow;
  }

  /// A [Client] with the default configuration.
  factory CupertinoClient.defaultSessionConfiguration() {
    final config = URLSessionConfiguration.defaultSessionConfiguration();
    return CupertinoClient.fromSessionConfiguration(config);
  }

  /// A [Client] configured with a [URLSessionConfiguration].
  factory CupertinoClient.fromSessionConfiguration(
      URLSessionConfiguration config) {
    final session = URLSession.sessionWithConfiguration(config,
        onComplete: _onComplete,
        onData: _onData,
        onRedirect: _onRedirect,
        onResponse: _onResponse);
    return CupertinoClient._(session);
  }

  @override
  void close() {
    _urlSession?.finishTasksAndInvalidate();
    _urlSession = null;
  }

  /// Returns true if [stream] includes at least one list with an element.
  ///
  /// Since [_hasData] consumes [stream], returns a new stream containing the
  /// equivalent data.
  static Future<(bool, Stream<List<int>>)> _hasData(
      Stream<List<int>> stream) async {
    final queue = StreamQueue(stream);
    while (await queue.hasNext && (await queue.peek).isEmpty) {
      await queue.next;
    }

    return (await queue.hasNext, queue.rest);
  }

  HttpClientRequestProfile? _createProfile(BaseRequest request) =>
      HttpClientRequestProfile.profile(
          requestStartTime: DateTime.now(),
          requestMethod: request.method,
          requestUri: request.url.toString());

  @override
  Future<StreamedResponse> send(BaseRequest request) async {
    // The expected success case flow (without redirects) is:
    // 1. send is called by BaseClient
    // 2. send starts the request with UrlSession.dataTaskWithRequest and waits
    //    on a Completer
    // 3. _onResponse is called with the HTTP headers, status code, etc.
    // 4. _onResponse calls complete on the Completer that send is waiting on.
    // 5. send continues executing and returns a StreamedResponse.
    //    StreamedResponse contains a Stream<UInt8List>.
    // 6. _onData is called one or more times and adds that to the
    //    StreamController that controls the Stream<UInt8List>
    // 7. _onComplete is called after all the data is read and closes the
    //    StreamController
    if (_urlSession == null) {
      throw ClientException(
          'HTTP request failed. Client is already closed.', request.url);
    }
    final urlSession = _urlSession!;

    final stream = request.finalize();

    final profile = _createProfile(request);
    profile?.connectionInfo = {
      'package': 'package:cupertino_http',
      'client': 'CupertinoClient',
      'configuration': _urlSession!.configuration.toString(),
    };
    profile?.requestData
      ?..contentLength = request.contentLength
      ..followRedirects = request.followRedirects
      ..headersCommaValues = request.headers
      ..maxRedirects = request.maxRedirects;

    final urlRequest = MutableURLRequest.fromUrl(request.url)
      ..httpMethod = request.method;

    if (request.contentLength != null) {
      profile?.requestData.headersListValues = {
        'Content-Length': ['${request.contentLength}'],
        ...profile.requestData.headers!
      };
      urlRequest.setValueForHttpHeaderField(
          'Content-Length', '${request.contentLength}');
    }

    if (request is Request) {
      // Optimize the (typical) `Request` case since assigning to
      // `httpBodyStream` requires a lot of expensive setup and data passing.
      urlRequest.httpBody = request.bodyBytes.toNSData();
      profile?.requestData.bodySink.add(request.bodyBytes);
    } else if (await _hasData(stream) case (true, final s)) {
      // If the request is supposed to be bodyless (e.g. GET requests)
      // then setting `httpBodyStream` will cause the request to fail -
      // even if the stream is empty.
      if (profile == null) {
        urlRequest.httpBodyStream = s.toNSInputStream();
      } else {
        final splitter = StreamSplitter(s);
        urlRequest.httpBodyStream = splitter.split().toNSInputStream();
        unawaited(profile.requestData.bodySink.addStream(splitter.split()));
      }
    }

    // This will preserve Apple default headers - is that what we want?
    request.headers.forEach(urlRequest.setValueForHttpHeaderField);
    final task = urlSession.dataTaskWithRequest(urlRequest);
    final taskTracker = _TaskTracker(request, profile);
    _tasks[task] = taskTracker;
    task.resume();

    final maxRedirects = request.followRedirects ? request.maxRedirects : 0;

    late URLResponse result;
    result = await taskTracker.responseCompleter.future;

    final response = result as HTTPURLResponse;

    if (request.followRedirects && taskTracker.numRedirects > maxRedirects) {
      throw ClientException('Redirect limit exceeded', request.url);
    }

    final responseHeaders = response.allHeaderFields
        .map((key, value) => MapEntry(key.toLowerCase(), value));

    if (responseHeaders['content-length'] case final contentLengthHeader?
        when !_digitRegex.hasMatch(contentLengthHeader)) {
      throw ClientException(
        'Invalid content-length header [$contentLengthHeader].',
        request.url,
      );
    }

    final contentLength = response.expectedContentLength == -1
        ? null
        : response.expectedContentLength;
    final isRedirect = !request.followRedirects && taskTracker.numRedirects > 0;
    profile?.responseData
      ?..contentLength = contentLength
      ..headersCommaValues = responseHeaders
      ..isRedirect = isRedirect
      ..reasonPhrase = _findReasonPhrase(response.statusCode)
      ..startTime = DateTime.now()
      ..statusCode = response.statusCode;

    return _StreamedResponseWithUrl(
      taskTracker.responseController.stream,
      response.statusCode,
      url: taskTracker.lastUrl ?? request.url,
      contentLength: contentLength,
      reasonPhrase: _findReasonPhrase(response.statusCode),
      request: request,
      isRedirect: isRedirect,
      headers: responseHeaders,
    );
  }
}

/// A test-only class that makes the [HttpClientRequestProfile] data available.
class CupertinoClientWithProfile extends CupertinoClient {
  HttpClientRequestProfile? profile;

  @override
  HttpClientRequestProfile? _createProfile(BaseRequest request) =>
      profile = super._createProfile(request);

  CupertinoClientWithProfile._(super._urlSession) : super._();

  factory CupertinoClientWithProfile.defaultSessionConfiguration() {
    final config = URLSessionConfiguration.defaultSessionConfiguration();
    final session = URLSession.sessionWithConfiguration(config,
        onComplete: CupertinoClient._onComplete,
        onData: CupertinoClient._onData,
        onRedirect: CupertinoClient._onRedirect,
        onResponse: CupertinoClient._onResponse);
    return CupertinoClientWithProfile._(session);
  }
}
