// 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 'package:archive/archive.dart';
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';

import 'common.dart';
import 'file_system.dart';
import 'io.dart';
import 'logger.dart';
import 'platform.dart';
import 'process.dart';

abstract class OperatingSystemUtils {
  factory OperatingSystemUtils({
    required FileSystem fileSystem,
    required Logger logger,
    required Platform platform,
    required ProcessManager processManager,
  }) {
    if (platform.isWindows) {
      return _WindowsUtils(
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
      );
    } else if (platform.isMacOS) {
      return _MacOSUtils(
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
      );
    } else if (platform.isLinux) {
      return _LinuxUtils(
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
      );
    } else {
      return _PosixUtils(
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
      );
    }
  }

  OperatingSystemUtils._private({
    required FileSystem fileSystem,
    required Logger logger,
    required Platform platform,
    required ProcessManager processManager,
  }) : _fileSystem = fileSystem,
       _logger = logger,
       _platform = platform,
       _processManager = processManager,
       _processUtils = ProcessUtils(
        logger: logger,
        processManager: processManager,
      );

  @visibleForTesting
  static final GZipCodec gzipLevel1 = GZipCodec(level: 1);

  final FileSystem _fileSystem;
  final Logger _logger;
  final Platform _platform;
  final ProcessManager _processManager;
  final ProcessUtils _processUtils;

  /// Make the given file executable. This may be a no-op on some platforms.
  void makeExecutable(File file);

  /// Updates the specified file system [entity] to have the file mode
  /// bits set to the value defined by [mode], which can be specified in octal
  /// (e.g. `644`) or symbolically (e.g. `u+x`).
  ///
  /// On operating systems that do not support file mode bits, this will be a
  /// no-op.
  void chmod(FileSystemEntity entity, String mode);

  /// Return the path (with symlinks resolved) to the given executable, or null
  /// if `which` was not able to locate the binary.
  File? which(String execName) {
    final List<File> result = _which(execName);
    if (result == null || result.isEmpty) {
      return null;
    }
    return result.first;
  }

  /// Return a list of all paths to `execName` found on the system. Uses the
  /// PATH environment variable.
  List<File> whichAll(String execName) => _which(execName, all: true);

  /// Return the File representing a new pipe.
  File makePipe(String path);

  void unzip(File file, Directory targetDirectory);

  void unpack(File gzippedTarFile, Directory targetDirectory);

  /// Compresses a stream using gzip level 1 (faster but larger).
  Stream<List<int>> gzipLevel1Stream(Stream<List<int>> stream) {
    return stream.cast<List<int>>().transform<List<int>>(gzipLevel1.encoder);
  }

  /// Returns a pretty name string for the current operating system.
  ///
  /// If available, the detailed version of the OS is included.
  String get name {
    const Map<String, String> osNames = <String, String>{
      'macos': 'Mac OS',
      'linux': 'Linux',
      'windows': 'Windows',
    };
    final String osName = _platform.operatingSystem;
    return osNames[osName] ?? osName;
  }

  HostPlatform get hostPlatform;

  List<File> _which(String execName, { bool all = false });

  /// Returns the separator between items in the PATH environment variable.
  String get pathVarSeparator;

  /// Returns an unused network port.
  ///
  /// Returns 0 if an unused port cannot be found.
  ///
  /// The port returned by this function may become used before it is bound by
  /// its intended user.
  Future<int> findFreePort({bool ipv6 = false}) async {
    int port = 0;
    ServerSocket? serverSocket;
    final InternetAddress loopback =
        ipv6 ? InternetAddress.loopbackIPv6 : InternetAddress.loopbackIPv4;
    try {
      serverSocket = await ServerSocket.bind(loopback, 0);
      port = serverSocket.port;
    } on SocketException catch (e) {
      // If ipv4 loopback bind fails, try ipv6.
      if (!ipv6) {
        return findFreePort(ipv6: true);
      }
      _logger.printTrace('findFreePort failed: $e');
    } on Exception catch (e) {
      // Failures are signaled by a return value of 0 from this function.
      _logger.printTrace('findFreePort failed: $e');
    } finally {
      if (serverSocket != null) {
        await serverSocket.close();
      }
    }
    return port;
  }
}

class _PosixUtils extends OperatingSystemUtils {
  _PosixUtils({
    required FileSystem fileSystem,
    required Logger logger,
    required Platform platform,
    required ProcessManager processManager,
  }) : super._private(
    fileSystem: fileSystem,
    logger: logger,
    platform: platform,
    processManager: processManager,
  );

  @override
  void makeExecutable(File file) {
    chmod(file, 'a+x');
  }

  @override
  void chmod(FileSystemEntity entity, String mode) {
    try {
      final ProcessResult result = _processManager.runSync(
        <String>['chmod', mode, entity.path],
      );
      if (result.exitCode != 0) {
        _logger.printTrace(
          'Error trying to run chmod on ${entity.absolute.path}'
          '\nstdout: ${result.stdout}'
          '\nstderr: ${result.stderr}',
        );
      }
    } on ProcessException catch (error) {
      _logger.printTrace(
        'Error trying to run chmod on ${entity.absolute.path}: $error',
      );
    }
  }

  @override
  List<File> _which(String execName, { bool all = false }) {
    final List<String> command = <String>[
      'which',
      if (all) '-a',
      execName,
    ];
    final ProcessResult result = _processManager.runSync(command);
    if (result.exitCode != 0) {
      return const <File>[];
    }
    final String stdout = result.stdout as String;
    return stdout.trim().split('\n').map<File>(
      (String path) => _fileSystem.file(path.trim()),
    ).toList();
  }

  // unzip -o -q zipfile -d dest
  @override
  void unzip(File file, Directory targetDirectory) {
    if (!_processManager.canRun('unzip')) {
      // unzip is not available. this error message is modeled after the download
      // error in bin/internal/update_dart_sdk.sh
      String message = 'Please install unzip.';
      if (_platform.isMacOS) {
        message = 'Consider running "brew install unzip".';
      } else if (_platform.isLinux) {
        message = 'Consider running "sudo apt-get install unzip".';
      }
      throwToolExit(
        'Missing "unzip" tool. Unable to extract ${file.path}.\n$message'
      );
    }
    _processUtils.runSync(
      <String>['unzip', '-o', '-q', file.path, '-d', targetDirectory.path],
      throwOnError: true,
      verboseExceptions: true,
    );
  }

  // tar -xzf tarball -C dest
  @override
  void unpack(File gzippedTarFile, Directory targetDirectory) {
    _processUtils.runSync(
      <String>['tar', '-xzf', gzippedTarFile.path, '-C', targetDirectory.path],
      throwOnError: true,
    );
  }

  @override
  File makePipe(String path) {
    _processUtils.runSync(
      <String>['mkfifo', path],
      throwOnError: true,
    );
    return _fileSystem.file(path);
  }

  @override
  String get pathVarSeparator => ':';

  HostPlatform? _hostPlatform;

  @override
  HostPlatform get hostPlatform {
    if (_hostPlatform == null) {
      final RunResult hostPlatformCheck =
          _processUtils.runSync(<String>['uname', '-m']);
      // On x64 stdout is "uname -m: x86_64"
      // On arm64 stdout is "uname -m: aarch64, arm64_v8a"
      if (hostPlatformCheck.exitCode != 0) {
        _logger.printError(
          'Error trying to run uname -m'
          '\nstdout: ${hostPlatformCheck.stdout}'
          '\nstderr: ${hostPlatformCheck.stderr}',
        );
        _hostPlatform = HostPlatform.linux_x64;
      } else if (hostPlatformCheck.stdout.trim().endsWith('x86_64')) {
        _hostPlatform = HostPlatform.linux_x64;
      } else {
        _hostPlatform = HostPlatform.linux_arm64;
      }
    }
    return _hostPlatform!;
  }
}

class _LinuxUtils extends _PosixUtils {
  _LinuxUtils({
    required FileSystem fileSystem,
    required Logger logger,
    required Platform platform,
    required ProcessManager processManager,
  }) : super(
          fileSystem: fileSystem,
          logger: logger,
          platform: platform,
          processManager: processManager,
        );

  String? _name;

  @override
  String get name {
    if (_name == null) {
      const String prettyNameKey = 'PRETTY_NAME';
      // If "/etc/os-release" doesn't exist, fallback to "/usr/lib/os-release".
      final String osReleasePath = _fileSystem.file('/etc/os-release').existsSync()
        ? '/etc/os-release'
        : '/usr/lib/os-release';
      String prettyName;
      String kernelRelease;
      try {
        final String osRelease = _fileSystem.file(osReleasePath).readAsStringSync();
        prettyName = _getOsReleaseValueForKey(osRelease, prettyNameKey);
      } on Exception catch (e) {
        _logger.printTrace('Failed obtaining PRETTY_NAME for Linux: $e');
        prettyName = '';
      }
      try {
        // Split the operating system version which should be formatted as
        // "Linux kernelRelease build", by spaces.
        final List<String> osVersionSplitted = _platform.operatingSystemVersion.split(' ');
        if (osVersionSplitted.length < 3) {
          // The operating system version didn't have the expected format.
          // Initialize as an empty string.
          kernelRelease = '';
        } else {
          kernelRelease = ' ${osVersionSplitted[1]}';
        }
      } on Exception catch (e) {
        _logger.printTrace('Failed obtaining kernel release for Linux: $e');
        kernelRelease = '';
      }
      _name = '${prettyName.isEmpty ? super.name : prettyName}$kernelRelease';
    }
    return _name!;
  }

  String _getOsReleaseValueForKey(String osRelease, String key) {
    final List<String> osReleaseSplitted = osRelease.split('\n');
    for (String entry in osReleaseSplitted) {
      entry = entry.trim();
      final List<String> entryKeyValuePair = entry.split('=');
      if(entryKeyValuePair[0] == key) {
        final String value =  entryKeyValuePair[1];
        // Remove quotes from either end of the value if they exist
        final String quote = value[0];
        if (quote == "'" || quote == '"') {
          return value.substring(0, value.length - 1).substring(1);
        } else {
          return value;
        }
      }
    }
    return '';
  }
}

class _MacOSUtils extends _PosixUtils {
  _MacOSUtils({
    required FileSystem fileSystem,
    required Logger logger,
    required Platform platform,
    required ProcessManager processManager,
  }) : super(
          fileSystem: fileSystem,
          logger: logger,
          platform: platform,
          processManager: processManager,
        );

  String? _name;

  @override
  String get name {
    if (_name == null) {
      final List<RunResult> results = <RunResult>[
        _processUtils.runSync(<String>['sw_vers', '-productName']),
        _processUtils.runSync(<String>['sw_vers', '-productVersion']),
        _processUtils.runSync(<String>['sw_vers', '-buildVersion']),
      ];
      if (results.every((RunResult result) => result.exitCode == 0)) {
        _name =
            '${results[0].stdout.trim()} ${results[1].stdout.trim()} ${results[2].stdout.trim()} ${getNameForHostPlatform(hostPlatform)}';
      }
      _name ??= super.name;
    }
    return _name!;
  }

  // On ARM returns arm64, even when this process is running in Rosetta.
  @override
  HostPlatform get hostPlatform {
    if (_hostPlatform == null) {
      String? sysctlPath;
      if (which('sysctl') == null) {
        // Fallback to known install locations.
        for (final String path in <String>[
          '/usr/sbin/sysctl',
          '/sbin/sysctl',
        ]) {
          if (_fileSystem.isFileSync(path)) {
            sysctlPath = path;
          }
        }
      } else {
        sysctlPath = 'sysctl';
      }

      if (sysctlPath == null) {
        throwToolExit('sysctl not found. Try adding it to your PATH environment variable.');
      }
      final RunResult arm64Check =
          _processUtils.runSync(<String>[sysctlPath, 'hw.optional.arm64']);
      // On arm64 stdout is "sysctl hw.optional.arm64: 1"
      // On x86 hw.optional.arm64 is unavailable and exits with 1.
      if (arm64Check.exitCode == 0 && arm64Check.stdout.trim().endsWith('1')) {
        _hostPlatform = HostPlatform.darwin_arm;
      } else {
        _hostPlatform = HostPlatform.darwin_x64;
      }
    }
    return _hostPlatform!;
  }

  // unzip, then rsync
  @override
  void unzip(File file, Directory targetDirectory) {
    if (!_processManager.canRun('unzip')) {
      // unzip is not available. this error message is modeled after the download
      // error in bin/internal/update_dart_sdk.sh
      throwToolExit('Missing "unzip" tool. Unable to extract ${file.path}.\nConsider running "brew install unzip".');
    }
    if (_processManager.canRun('rsync')) {
      final Directory tempDirectory = _fileSystem.systemTempDirectory.createTempSync('flutter_${file.basename}.');
      try {
        // Unzip to a temporary directory.
        _processUtils.runSync(
          <String>['unzip', '-o', '-q', file.path, '-d', tempDirectory.path],
          throwOnError: true,
          verboseExceptions: true,
        );
        for (final FileSystemEntity unzippedFile in tempDirectory.listSync(followLinks: false)) {
          // rsync --delete the unzipped files so files removed from the archive are also removed from the target.
          _processUtils.runSync(
            <String>['rsync', '-av', '--delete', unzippedFile.path, targetDirectory.path],
            throwOnError: true,
            verboseExceptions: true,
          );
        }
      } finally {
        tempDirectory.deleteSync(recursive: true);
      }
    } else {
      // Fall back to just unzipping.
      _logger.printTrace('Unable to find rsync, falling back to direct unzipping.');
      _processUtils.runSync(
        <String>['unzip', '-o', '-q', file.path, '-d', targetDirectory.path],
        throwOnError: true,
        verboseExceptions: true,
      );
    }
  }
}

class _WindowsUtils extends OperatingSystemUtils {
  _WindowsUtils({
    required FileSystem fileSystem,
    required Logger logger,
    required Platform platform,
    required ProcessManager processManager,
  }) : super._private(
    fileSystem: fileSystem,
    logger: logger,
    platform: platform,
    processManager: processManager,
  );

  @override
  HostPlatform hostPlatform = HostPlatform.windows_x64;

  @override
  void makeExecutable(File file) {}

  @override
  void chmod(FileSystemEntity entity, String mode) {}

  @override
  List<File> _which(String execName, { bool all = false }) {
    if (!_processManager.canRun('where')) {
      // `where` could be missing if system32 is not on the PATH.
      throwToolExit(
        'Cannot find the executable for `where`. This can happen if the System32 '
        r'folder (e.g. C:\Windows\System32 ) is removed from the PATH environment '
        'variable. Ensure that this is present and then try again after restarting '
        'the terminal and/or IDE.'
      );
    }
    // `where` always returns all matches, not just the first one.
    final ProcessResult result = _processManager.runSync(<String>['where', execName]);
    if (result.exitCode != 0) {
      return const <File>[];
    }
    final List<String> lines = (result.stdout as String).trim().split('\n');
    if (all) {
      return lines.map<File>((String path) => _fileSystem.file(path.trim())).toList();
    }
    return <File>[_fileSystem.file(lines.first.trim())];
  }

  @override
  void unzip(File file, Directory targetDirectory) {
    final Archive archive = ZipDecoder().decodeBytes(file.readAsBytesSync());
    _unpackArchive(archive, targetDirectory);
  }

  @override
  void unpack(File gzippedTarFile, Directory targetDirectory) {
    final Archive archive = TarDecoder().decodeBytes(
      GZipDecoder().decodeBytes(gzippedTarFile.readAsBytesSync()),
    );
    _unpackArchive(archive, targetDirectory);
  }

  void _unpackArchive(Archive archive, Directory targetDirectory) {
    for (final ArchiveFile archiveFile in archive.files) {
      // The archive package doesn't correctly set isFile.
      if (!archiveFile.isFile || archiveFile.name.endsWith('/')) {
        continue;
      }

      final File destFile = _fileSystem.file(_fileSystem.path.join(
        targetDirectory.path,
        archiveFile.name,
      ));
      if (!destFile.parent.existsSync()) {
        destFile.parent.createSync(recursive: true);
      }
      destFile.writeAsBytesSync(archiveFile.content as List<int>);
    }
  }

  @override
  File makePipe(String path) {
    throw UnsupportedError('makePipe is not implemented on Windows.');
  }

  String? _name;

  @override
  String get name {
    if (_name == null) {
      final ProcessResult result = _processManager.runSync(
          <String>['ver'], runInShell: true);
      if (result.exitCode == 0) {
        _name = (result.stdout as String).trim();
      } else {
        _name = super.name;
      }
    }
    return _name!;
  }

  @override
  String get pathVarSeparator => ';';
}

/// Find and return the project root directory relative to the specified
/// directory or the current working directory if none specified.
/// Return null if the project root could not be found
/// or if the project root is the flutter repository root.
String? findProjectRoot(FileSystem fileSystem, [ String? directory ]) {
  const String kProjectRootSentinel = 'pubspec.yaml';
  directory ??= fileSystem.currentDirectory.path;
  while (true) {
    if (fileSystem.isFileSync(fileSystem.path.join(directory!, kProjectRootSentinel))) {
      return directory;
    }
    final String parent = fileSystem.path.dirname(directory);
    if (directory == parent) {
      return null;
    }
    directory = parent;
  }
}

enum HostPlatform {
  darwin_x64,
  darwin_arm,
  linux_x64,
  linux_arm64,
  windows_x64,
}

String getNameForHostPlatform(HostPlatform platform) {
  switch (platform) {
    case HostPlatform.darwin_x64:
      return 'darwin-x64';
    case HostPlatform.darwin_arm:
      return 'darwin-arm';
    case HostPlatform.linux_x64:
      return 'linux-x64';
    case HostPlatform.linux_arm64:
      return 'linux-arm64';
    case HostPlatform.windows_x64:
      return 'windows-x64';
  }
}
