// 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.

/// @assertion void authenticate=(
///    Future<bool> f(
///      Uri url,
///      String scheme,
///      String realm
///    )
/// )
/// Sets the function to be called when a site is requesting authentication.
/// The URL requested and the security realm from the server are passed in the
/// arguments url and realm.
///
/// The function returns a Future which should complete when the authentication
/// has been resolved. If credentials cannot be provided the Future should
/// complete with false. If credentials are available the function should add
/// these using addCredentials before completing the Future with the value true.
///
/// If the Future completes with true the request will be retried using the
/// updated credentials. Otherwise response processing will continue normally.
/// @description Checks that this setter sets the function to be called when a
/// site is requesting authentication. Test Digest authentication
/// @author sgrekhov@unipro.ru

import "dart:io";
import 'dart:async';
import "dart:convert";
import "../../../Utils/expect.dart";

test() async {
  HttpServer server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
  server.listen((HttpRequest request) {
    if (request.headers[HttpHeaders.authorizationHeader] == null) {
      request.response.statusCode = HttpStatus.unauthorized;
      StringBuffer authHeader = new StringBuffer();
      authHeader.write('Digest');
      authHeader.write(', realm="realm"');
      authHeader.write(', nonce="123"');
      authHeader.write(', domain="/xxxt/"');
      request.response.headers.set(HttpHeaders.wwwAuthenticateHeader, authHeader);
      request.response.close();
    } else {
      var authorization = request.headers[HttpHeaders.authorizationHeader]?[0];
      Expect.isTrue(authorization?.contains('Digest'));
      Expect.isTrue(authorization?.contains('username="co19-test"'));
      Expect.isTrue(authorization?.contains('realm="realm"'));
      Expect.isTrue(authorization?.contains('algorithm="MD5"'));
      Expect.isTrue(authorization?.contains('uri="/xxx"'));
      request.response.close();
      server.close();
      asyncEnd();
    }
  });
  HttpClient client = new HttpClient();

  client.authenticate = (Uri url, String scheme, String? realm) {
    Expect.equals("Digest", scheme);
    Expect.equals("realm", realm);
    Completer<bool> completer = new Completer<bool>();
    client.addCredentials(
        Uri.parse(
            "http://${InternetAddress.loopbackIPv4.address}:${server.port}/xxx"),
        "realm",
        new HttpClientDigestCredentials("co19-test", "password"));
    completer.complete(true);

    return completer.future;
  };

  client
      .getUrl(Uri.parse(
          "http://${InternetAddress.loopbackIPv4.address}:${server.port}/xxx"))
      .then((HttpClientRequest request) => request.close())
      .then((HttpClientResponse response) {
    response.cast<List<int>>().transform(utf8.decoder).listen((content) {});
  });
}

main() {
  asyncStart();
  test();
}
