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

import 'dart:async';

import 'package:meta/meta.dart';

import '../convert.dart';
import 'common.dart';
import 'file_system.dart';
import 'io.dart';
import 'logger.dart';
import 'platform.dart';

const int kNetworkProblemExitCode = 50;

typedef HttpClientFactory = HttpClient Function();

typedef UrlTunneller = Future<String> Function(String url);

/// If [httpClientFactory] is null, a default [HttpClient] is used.
class Net {
  Net({
    HttpClientFactory? httpClientFactory,
    required Logger logger,
    required Platform platform,
  }) :
    _httpClientFactory = httpClientFactory ?? (() => HttpClient()),
    _logger = logger,
    _platform = platform;

  final HttpClientFactory _httpClientFactory;

  final Logger _logger;

  final Platform _platform;

  /// Download a file from the given URL.
  ///
  /// If a destination file is not provided, returns the bytes.
  ///
  /// If a destination file is provided, streams the bytes to that file and
  /// returns an empty list.
  ///
  /// If [maxAttempts] is exceeded, returns null.
  Future<List<int>?> fetchUrl(Uri url, {
    int? maxAttempts,
    File? destFile,
    @visibleForTesting Duration? durationOverride,
  }) async {
    int attempts = 0;
    int durationSeconds = 1;
    while (true) {
      attempts += 1;
      _MemoryIOSink? memorySink;
      IOSink sink;
      if (destFile == null) {
        memorySink = _MemoryIOSink();
        sink = memorySink;
      } else {
        sink = destFile.openWrite();
      }

      final bool result = await _attempt(
        url,
        destSink: sink,
      );
      if (result) {
        return memorySink?.writes.takeBytes() ?? <int>[];
      }

      if (maxAttempts != null && attempts >= maxAttempts) {
        _logger.printStatus('Download failed -- retry $attempts');
        return null;
      }
      _logger.printStatus(
        'Download failed -- attempting retry $attempts in '
        '$durationSeconds second${ durationSeconds == 1 ? "" : "s"}...',
      );
      await Future<void>.delayed(durationOverride ?? Duration(seconds: durationSeconds));
      if (durationSeconds < 64) {
        durationSeconds *= 2;
      }
    }
  }

  /// Check if the given URL points to a valid endpoint.
  Future<bool> doesRemoteFileExist(Uri url) => _attempt(url, onlyHeaders: true);

  // Returns true on success and false on failure.
  Future<bool> _attempt(Uri url, {
    IOSink? destSink,
    bool onlyHeaders = false,
  }) async {
    assert(onlyHeaders || destSink != null);
    _logger.printTrace('Downloading: $url');
    final HttpClient httpClient = _httpClientFactory();
    HttpClientRequest request;
    HttpClientResponse? response;
    try {
      if (onlyHeaders) {
        request = await httpClient.headUrl(url);
      } else {
        request = await httpClient.getUrl(url);
      }
      response = await request.close();
    } on ArgumentError catch (error) {
      final String? overrideUrl = _platform.environment['FLUTTER_STORAGE_BASE_URL'];
      if (overrideUrl != null && url.toString().contains(overrideUrl)) {
        _logger.printError(error.toString());
        throwToolExit(
          'The value of FLUTTER_STORAGE_BASE_URL ($overrideUrl) could not be '
          'parsed as a valid url. Please see https://flutter.dev/community/china '
          'for an example of how to use it.\n'
          'Full URL: $url',
          exitCode: kNetworkProblemExitCode,);
      }
      _logger.printError(error.toString());
      rethrow;
    } on HandshakeException catch (error) {
      _logger.printTrace(error.toString());
      throwToolExit(
        'Could not authenticate download server. You may be experiencing a man-in-the-middle attack,\n'
        'your network may be compromised, or you may have malware installed on your computer.\n'
        'URL: $url',
        exitCode: kNetworkProblemExitCode,
      );
    } on SocketException catch (error) {
      _logger.printTrace('Download error: $error');
      return false;
    } on HttpException catch (error) {
      _logger.printTrace('Download error: $error');
      return false;
    }
    assert(response != null);

    // If we're making a HEAD request, we're only checking to see if the URL is
    // valid.
    if (onlyHeaders) {
      return response.statusCode == HttpStatus.ok;
    }
    if (response.statusCode != HttpStatus.ok) {
      if (response.statusCode > 0 && response.statusCode < 500) {
        throwToolExit(
          'Download failed.\n'
          'URL: $url\n'
          'Error: ${response.statusCode} ${response.reasonPhrase}',
          exitCode: kNetworkProblemExitCode,
        );
      }
      // 5xx errors are server errors and we can try again
      _logger.printTrace('Download error: ${response.statusCode} ${response.reasonPhrase}');
      return false;
    }
    _logger.printTrace('Received response from server, collecting bytes...');
    try {
      assert(destSink != null);
      await response.forEach(destSink!.add);
      return true;
    } on IOException catch (error) {
      _logger.printTrace('Download error: $error');
      return false;
    } finally {
      await destSink?.flush();
      await destSink?.close();
    }
  }
}

/// An IOSink that collects whatever is written to it.
class _MemoryIOSink implements IOSink {
  @override
  Encoding encoding = utf8;

  final BytesBuilder writes = BytesBuilder(copy: false);

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

  @override
  Future<void> addStream(Stream<List<int>> stream) {
    final Completer<void> completer = Completer<void>();
    stream.listen(add).onDone(completer.complete);
    return completer.future;
  }

  @override
  void writeCharCode(int charCode) {
    add(<int>[charCode]);
  }

  @override
  void write(Object? obj) {
    add(encoding.encode('$obj'));
  }

  @override
  void writeln([ Object? obj = '' ]) {
    add(encoding.encode('$obj\n'));
  }

  @override
  void writeAll(Iterable<dynamic> objects, [ String separator = '' ]) {
    bool addSeparator = false;
    for (final dynamic object in objects) {
      if (addSeparator) {
        write(separator);
      }
      write(object);
      addSeparator = true;
    }
  }

  @override
  void addError(dynamic error, [ StackTrace? stackTrace ]) {
    throw UnimplementedError();
  }

  @override
  Future<void> get done => close();

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

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

/// Returns [true] if [address] is an IPv6 address.
bool isIPv6Address(String address) {
  try {
    Uri.parseIPv6Address(address);
    return true;
  } on FormatException {
    return false;
  }
}
