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

// @dart = 2.8

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

class Net {
  Net({
    HttpClientFactory httpClientFactory,
    @required Logger logger,
    @required Platform platform,
  }) :
    _httpClientFactory = httpClientFactory,
    _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,
  }) 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(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');
    HttpClient httpClient;
    if (_httpClientFactory != null) {
      httpClient = _httpClientFactory();
    } else {
      httpClient = HttpClient();
    }
    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;
  }
}
