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

import 'dart:io' as io;

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

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

/// Returns the installation of Firefox, installing it if necessary.
///
/// If [requestedVersion] is null, uses the version specified on the
/// command-line. If not specified on the command-line, uses the version
/// specified in the "browser_lock.yaml" file.
///
/// If [requestedVersion] is not null, installs that version. The value
/// may be "latest" (the latest stable Firefox version), "system"
/// (manually installed Firefox on the current operating system), or an
/// exact version number such as 69.0.3. Versions of Firefox can be found here:
///
/// https://download-installer.cdn.mozilla.net/pub/firefox/releases/
Future<BrowserInstallation> getOrInstallFirefox(
  String requestedVersion, {
  StringSink? infoLog,
}) async {
  // These tests are aimed to run only on the Linux containers in Cirrus.
  // Therefore Firefox installation is implemented only for Linux now.
  if (!io.Platform.isLinux && !io.Platform.isMacOS) {
    throw UnimplementedError('Firefox Installer is only supported on Linux '
        'and Mac operating systems');
  }

  infoLog ??= io.stdout;

  if (requestedVersion == 'system') {
    return BrowserInstallation(
      version: 'system',
      executable: await _findSystemFirefoxExecutable(),
    );
  }

  FirefoxInstaller? installer;
  try {
    installer = requestedVersion == 'latest'
        ? await FirefoxInstaller.latest()
        : FirefoxInstaller(version: requestedVersion);

    if (installer.isInstalled) {
      infoLog.writeln(
          'Installation was skipped because Firefox version ${installer.version} is already installed.');
    } else {
      infoLog.writeln('Installing Firefox version: ${installer.version}');
      await installer.install();
      final BrowserInstallation installation = installer.getInstallation()!;
      infoLog.writeln(
          'Installations complete. To launch it run ${installation.executable}');
    }
    return installer.getInstallation()!;
  } finally {
    installer?.close();
  }
}

/// Manages the installation of a particular [version] of Firefox.
class FirefoxInstaller {
  factory FirefoxInstaller({
    required String version,
  }) {
    if (version == 'system') {
      throw BrowserInstallerException(
          'Cannot install system version of Firefox. System Firefox must be installed manually.');
    }
    if (version == 'latest') {
      throw BrowserInstallerException(
          'Expected a concrete Firefox version, but got $version. Maybe use FirefoxInstaller.latest()?');
    }
    final io.Directory firefoxInstallationDir = io.Directory(
      path.join(environment.webUiDartToolDir.path, 'firefox'),
    );
    final io.Directory versionDir = io.Directory(
      path.join(firefoxInstallationDir.path, version),
    );
    return FirefoxInstaller._(
      version: version,
      firefoxInstallationDir: firefoxInstallationDir,
      versionDir: versionDir,
    );
  }

  FirefoxInstaller._({
    required this.version,
    required this.firefoxInstallationDir,
    required this.versionDir,
  });

  static Future<FirefoxInstaller> latest() async {
    final String latestVersion = io.Platform.isLinux
        ? await fetchLatestFirefoxVersionLinux()
        : await fetchLatestFirefoxVersionMacOS();
    return FirefoxInstaller(version: latestVersion);
  }

  /// Firefox version managed by this installer.
  final String version;

  /// HTTP client used to download Firefox.
  final Client client = Client();

  /// Root directory that contains Firefox versions.
  final io.Directory firefoxInstallationDir;

  /// Installation directory for Firefox of the requested [version].
  final io.Directory versionDir;

  bool get isInstalled {
    return versionDir.existsSync();
  }

  BrowserInstallation? getInstallation() {
    if (!isInstalled) {
      return null;
    }

    return BrowserInstallation(
      version: version,
      executable: PlatformBinding.instance.getFirefoxExecutablePath(versionDir),
    );
  }

  /// Install the browser by downloading from the web.
  Future<void> install() async {
    final io.File downloadedFile = await _download();
    if (io.Platform.isLinux) {
      await _uncompress(downloadedFile);
    } else if (io.Platform.isMacOS) {
      await _mountDmgAndCopy(downloadedFile);
    }
    downloadedFile.deleteSync();
  }

  /// Downloads the browser version from web into a target file.
  /// See [version].
  Future<io.File> _download() async {
    if (versionDir.existsSync()) {
      versionDir.deleteSync(recursive: true);
    }

    versionDir.createSync(recursive: true);
    final String url = PlatformBinding.instance.getFirefoxDownloadUrl(version);
    final StreamedResponse download = await client.send(Request(
      'GET',
      Uri.parse(url),
    ));

    final io.File downloadedFile =
        io.File(path.join(versionDir.path, PlatformBinding.instance.getFirefoxDownloadFilename(version)));
    final io.IOSink sink = downloadedFile.openWrite();
    await download.stream.pipe(sink);
    await sink.flush();
    await sink.close();

    return downloadedFile;
  }

  /// Uncompress the downloaded browser files for operating systems that
  /// use a zip archive.
  /// See [version].
  Future<void> _uncompress(io.File downloadedFile) async {
    final io.ProcessResult unzipResult = await io.Process.run('tar', <String>[
      '-x',
      '-f',
      downloadedFile.path,
      '-C',
      versionDir.path,
    ]);

    if (unzipResult.exitCode != 0) {
      throw BrowserInstallerException(
          'Failed to unzip the downloaded Firefox archive ${downloadedFile.path}.\n'
          'The unzip process exited with code ${unzipResult.exitCode}.');
    }
  }

  /// Mounts the dmg file using hdiutil, copies content of the volume to
  /// target path and then unmounts dmg ready for deletion.
  Future<void> _mountDmgAndCopy(io.File dmgFile) async {
    final String volumeName = await _hdiUtilMount(dmgFile);

    final String sourcePath = '$volumeName/Firefox.app';
    final String targetPath = path.dirname(dmgFile.path);
    try {
      final io.ProcessResult installResult = await io.Process.run('cp', <String>[
        '-r',
        sourcePath,
        targetPath,
      ]);
      if (installResult.exitCode != 0) {
        throw BrowserInstallerException(
            'Failed to copy Firefox disk image contents from '
            '$sourcePath to $targetPath.\n'
            'Exit code ${installResult.exitCode}.\n'
            '${installResult.stderr}');
      }
    } finally {
      await _hdiUtilUnmount(volumeName);
    }
  }

  Future<String> _hdiUtilMount(io.File dmgFile) async {
    final io.ProcessResult mountResult = await io.Process.run('hdiutil', <String>[
      'attach',
      '-readonly',
      dmgFile.path,
    ]);
    if (mountResult.exitCode != 0) {
      throw BrowserInstallerException(
          'Failed to mount Firefox disk image ${dmgFile.path}.\n'
              'Exit code ${mountResult.exitCode}.\n${mountResult.stderr}');
    }

    final List<String> processOutput = (mountResult.stdout as String).split('\n');
    final String? volumePath = _volumeFromMountResult(processOutput);
    if (volumePath == null) {
      throw BrowserInstallerException(
          'Failed to parse mount dmg result ${processOutput.join('\n')}.\n'
              'Expected /Volumes/{volume name}');
    }
    return volumePath;
  }

  // Parses volume from mount result.
  // Output is of form: {devicename} /Volumes/{name}.
  String? _volumeFromMountResult(List<String> lines) {
    for (final String line in lines) {
      final int pos = line.indexOf('/Volumes');
      if (pos != -1) {
        return line.substring(pos);
      }
    }
    return null;
  }

  Future<void> _hdiUtilUnmount(String volumeName) async {
    final io.ProcessResult unmountResult = await io.Process.run('hdiutil', <String>[
      'unmount',
      volumeName,
    ]);
    if (unmountResult.exitCode != 0) {
      throw BrowserInstallerException(
          'Failed to unmount Firefox disk image $volumeName.\n'
              'Exit code ${unmountResult.exitCode}. ${unmountResult.stderr}');
    }
  }

  void close() {
    client.close();
  }
}

Future<String> _findSystemFirefoxExecutable() async {
  final io.ProcessResult which =
      await io.Process.run('which', <String>['firefox']);
  final bool found = which.exitCode != 0;
  const String fireFoxDefaultInstallPath =
      '/Applications/Firefox.app/Contents/MacOS/firefox';
  if (!found) {
    if (io.Platform.isMacOS &&
        io.File(fireFoxDefaultInstallPath).existsSync()) {
      return Future<String>.value(fireFoxDefaultInstallPath);
    }
    throw BrowserInstallerException(
        'Failed to locate system Firefox installation.');
  }
  return which.stdout as String;
}

/// Fetches the latest available Firefox build version on Linux.
Future<String> fetchLatestFirefoxVersionLinux() async {
  final RegExp forFirefoxVersion = RegExp('firefox-[0-9.]+[0-9]');
  final io.HttpClientRequest request = await io.HttpClient()
      .getUrl(Uri.parse(PlatformBinding.instance.getFirefoxLatestVersionUrl()));
  request.followRedirects = false;
  // We will parse the HttpHeaders to find the redirect location.
  final io.HttpClientResponse response = await request.close();

  final String location = response.headers.value('location')!;
  final String version = forFirefoxVersion.stringMatch(location)!;

  return version.substring(version.lastIndexOf('-') + 1);
}

/// Fetches the latest available Firefox build version on Mac OS.
Future<String> fetchLatestFirefoxVersionMacOS() async {
  final RegExp forFirefoxVersion = RegExp('firefox/releases/[0-9.]+[0-9]');
  final io.HttpClientRequest request = await io.HttpClient()
      .getUrl(Uri.parse(PlatformBinding.instance.getFirefoxLatestVersionUrl()));
  request.followRedirects = false;
  // We will parse the HttpHeaders to find the redirect location.
  final io.HttpClientResponse response = await request.close();

  final String location = response.headers.value('location')!;
  final String version = forFirefoxVersion.stringMatch(location)!;
  return version.substring(version.lastIndexOf('/') + 1);
}

Future<BrowserInstallation> getInstaller({String requestedVersion = 'latest'}) async {
  FirefoxInstaller? installer;
  try {
    installer = requestedVersion == 'latest'
        ? await FirefoxInstaller.latest()
        : FirefoxInstaller(version: requestedVersion);

    if (installer.isInstalled) {
      print('Installation was skipped because Firefox version '
          '${installer.version} is already installed.');
    } else {
      print('Installing Firefox version: ${installer.version}');
      await installer.install();
      final BrowserInstallation installation = installer.getInstallation()!;
      print(
          'Installations complete. To launch it run ${installation.executable}');
    }
    return installer.getInstallation()!;
  } finally {
    installer?.close();
  }
}
