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

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