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

// FlutterTesterOptions=--disallow-insecure-connections

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

import 'package:litetest/litetest.dart';

/// Asserts that `callback` throws an exception of type `T`.
Future<void> asyncExpectThrows<T>(Function callback) async {
  bool threw = false;
  try {
    await callback();
  } catch (e) {
    expect(e is T, true);
    threw = true;
  }
  expect(threw, true);
}

Future<String> getLocalHostIP() async {
  final List<NetworkInterface> interfaces = await NetworkInterface.list(
      includeLoopback: false, type: InternetAddressType.IPv4);
  return interfaces.first.addresses.first.address;
}

Future<void> bindServerAndTest(String serverHost,
    Future<void> Function(HttpClient client, Uri uri) testCode) async {
  final HttpClient httpClient = HttpClient();
  final HttpServer server = await HttpServer.bind(serverHost, 0);
  final Uri uri = Uri(scheme: 'http', host: serverHost, port: server.port);
  try {
    await testCode(httpClient, uri);
  } finally {
    httpClient.close(force: true);
    await server.close();
  }
}

/// Answers the question whether this computer supports binding to IPv6 addresses.
Future<bool> _supportsIPv6() async {
  try {
    final ServerSocket socket = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0);
    await socket.close();
    return true;
  } on SocketException catch (_) {
    return false;
  }
}

void main() {
  test('testWithLocalIP', () async {
    await bindServerAndTest(await getLocalHostIP(), (HttpClient httpClient, Uri httpUri) async {
      asyncExpectThrows<UnsupportedError>(
          () async =>  httpClient.getUrl(httpUri));
      asyncExpectThrows<UnsupportedError>(
          () async => runZoned(() => httpClient.getUrl(httpUri),
            zoneValues: <dynamic, dynamic>{#flutter.io.allow_http: 'foo'}));
      asyncExpectThrows<UnsupportedError>(
          () async => runZoned(() => httpClient.getUrl(httpUri),
            zoneValues: <dynamic, dynamic>{#flutter.io.allow_http: false}));
      await runZoned(() => httpClient.getUrl(httpUri),
        zoneValues: <dynamic, dynamic>{#flutter.io.allow_http: true});
    });
  });

  test('testWithHostname', () async {
    await bindServerAndTest(Platform.localHostname, (HttpClient httpClient, Uri httpUri) async {
      asyncExpectThrows<UnsupportedError>(
          () async =>  httpClient.getUrl(httpUri));

      final _MockZoneValue mockFoo = _MockZoneValue('foo');
      asyncExpectThrows<UnsupportedError>(
          () async => runZoned(() => httpClient.getUrl(httpUri),
            zoneValues: <dynamic, dynamic>{#flutter.io.allow_http: mockFoo}));
      expect(mockFoo.checked, isTrue);

      final _MockZoneValue mockFalse = _MockZoneValue(false);
      asyncExpectThrows<UnsupportedError>(
          () async => runZoned(() => httpClient.getUrl(httpUri),
            zoneValues: <dynamic, dynamic>{#flutter.io.allow_http: mockFalse}));
      expect(mockFalse.checked, isTrue);

      final _MockZoneValue mockTrue = _MockZoneValue(true);
      await runZoned(() => httpClient.getUrl(httpUri),
        zoneValues: <dynamic, dynamic>{#flutter.io.allow_http: mockTrue});
      expect(mockFalse.checked, isTrue);
    });
  });

  test('testWithLoopback', () async {
    await bindServerAndTest('127.0.0.1', (HttpClient httpClient, Uri uri) async {
      await httpClient.getUrl(Uri.parse('http://localhost:${uri.port}'));
      await httpClient.getUrl(Uri.parse('http://127.0.0.1:${uri.port}'));
    });
  });

  test('testWithIPV6', () async {
    if (await _supportsIPv6()) {
      await bindServerAndTest('::1', (HttpClient httpClient, Uri uri) async {
        await httpClient.getUrl(uri);
      });
    }
  });
}

class _MockZoneValue {
  _MockZoneValue(this._value);

  Object? _value;
  bool _falseChecked = false;
  bool _trueChecked = false;

  @override
  bool operator ==(Object o) {
    if(o == true) {
      _trueChecked = true;
    }
    if(o == false) {
      _falseChecked = true;
    }
    return _value == o;
  }

  bool get checked => _falseChecked && _trueChecked;

  @override
  int get hashCode => _value.hashCode;
}
