// Copyright 2013 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.6
import 'dart:async';
import 'dart:io' as io;

import 'package:args/args.dart';
import 'package:http/http.dart';
import 'package:path/path.dart' as path;

import 'common.dart';
import 'environment.dart';

class EdgeArgParser extends BrowserArgParser {
  static final EdgeArgParser _singletonInstance = EdgeArgParser._();

  /// The [EdgeArgParser] singleton.
  static EdgeArgParser get instance => _singletonInstance;

  String _version;

  EdgeArgParser._();

  @override
  void populateOptions(ArgParser argParser) {
    argParser
      ..addOption(
        'edge-version',
        defaultsTo: 'system',
        help: 'The Edge version to use while running tests. The Edge '
            'browser installed on the system is used as the only option now.',
      );
  }

  @override
  void parseOptions(ArgResults argResults) {
    _version = argResults['edge-version'] as String;
    assert(_version == 'system');
  }

  @override
  String get version => _version;
}

/// Returns the installation of Edge.
///
/// Currently uses the Edge version installed on the operating system.
///
/// As explained on the Microsoft help page: `Microsoft Edge comes
/// exclusively with Windows 10 and cannot be downloaded or installed separately.`
/// See: https://support.microsoft.com/en-us/help/17171/microsoft-edge-get-to-know
///
// TODO(nurhan): Investigate running tests for the tech preview downloads
// from the beta channel.
Future<BrowserInstallation> getEdgeInstallation(
  String requestedVersion, {
  StringSink infoLog,
}) async {
  // For now these tests are aimed to run only on Windows machines local or on LUCI/CI.
  // In the future we can investigate to run them on Android or on MacOS.
  if (!io.Platform.isWindows) {
    throw UnimplementedError(
        'Tests for Edge on ${io.Platform.operatingSystem} is'
        ' not supported.');
  }

  infoLog ??= io.stdout;

  if (requestedVersion == 'system') {
    // Since Edge is included in Windows, always assume there will be one on the
    // system.
    infoLog.writeln('Using the system version that is already installed.');
    final EdgeLauncher edgeLauncher = EdgeLauncher();
    if (edgeLauncher.isInstalled) {
      infoLog.writeln('Launcher installation was skipped, already installed.');
    } else {
      infoLog.writeln('Installing MicrosoftEdgeLauncher');
      await edgeLauncher.install();
      infoLog.writeln(
          'Installations complete. To launch it run ${edgeLauncher.executable}');
    }

    return BrowserInstallation(
      version: 'system',
      executable: io.Directory(path.join(
              edgeLauncher.launcherInstallationDir.path,
              '${PlatformBinding.instance.getCommandToRunEdge()}'))
          .path,
    );
  } else {
    infoLog.writeln('Unsupported version $requestedVersion.');
    throw UnimplementedError();
  }
}

/// `MicrosoftEdgeLauncher` is an executable for launching Edge.
///
/// It is useful for starting Edge from comand line or from a
/// batch script.
///
/// See: https://github.com/MicrosoftEdge/edge-launcher
class EdgeLauncher {
  /// Path to the directory that contains `MicrosoftEdgeLauncher.exe`.
  io.Directory get launcherInstallationDir => io.Directory(
        path.join(environment.webUiDartToolDir.path, 'microsoftedgelauncher',
            version),
      );

  io.File get executable => io.File(
      path.join(launcherInstallationDir.path, 'MicrosoftEdgeLauncher.exe'));

  bool get isInstalled => executable.existsSync();

  /// Version number launcher executable  `MicrosoftEdgeLauncher`.
  final String version;

  /// Url for downloading  `MicrosoftEdgeLauncher`.
  ///
  /// Only useful in Windows, hence not added to [PlatformBinding].
  String get windowsEdgeLauncherDownloadUrl =>
      'https://github.com/MicrosoftEdge/edge-launcher/releases/download/$version/MicrosoftEdgeLauncher.exe';

  EdgeLauncher()
      : version =
            BrowserLock.instance.configuration['edge']['launcher_version'] as String;

  /// Install the launcher if it does not exist in this system.
  void install() async {
    // Checks if the  `MicrosoftEdgeLauncher` executable exists.
    if (isInstalled) {
      return;
    }

    // Create directory for download.
    if (!launcherInstallationDir.existsSync()) {
      launcherInstallationDir.createSync(recursive: true);
    }

    final Client client = Client();

    try {
      // Download executable from Github.
      final StreamedResponse download = await client.send(Request(
        'GET',
        Uri.parse(windowsEdgeLauncherDownloadUrl),
      ));

      await download.stream.pipe(executable.openWrite());
    } finally {
      client.close();
    }
  }
}
