// 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';

typedef FutureFunction = Future<Object?> Function();

/// Asserts that `callback` throws an exception of type `T`.
Future<void> asyncExpectThrows<T>(FutureFunction 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(
      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);
    });
  }, skip: Platform.isMacOS); // https://github.com/flutter/flutter/issues/141149

  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);

  final 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;
}
