// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. 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:file/file.dart';
import 'package:file/local.dart';
import 'package:path/path.dart' show Context;
import 'package:platform/platform.dart';

import 'exceptions.dart';

const Map<String, String> _osToPathStyle = <String, String>{
  'linux': 'posix',
  'macos': 'posix',
  'android': 'posix',
  'ios': 'posix',
  'fuchsia': 'posix',
  'windows': 'windows',
};

/// Searches the `PATH` for the executable that [executable] is supposed to launch.
///
/// This first builds a list of candidate paths where the executable may reside.
/// If [executable] is already an absolute path, then the `PATH` environment
/// variable will not be consulted, and the specified absolute path will be the
/// only candidate that is considered.
///
/// Once the list of candidate paths has been constructed, this will pick the
/// first such path that represents an existent file.
///
/// Return `null` if there were no viable candidates, meaning the executable
/// could not be found.
///
/// If [platform] is not specified, it will default to the current platform.
String? getExecutablePath(
  String executable,
  String? workingDirectory, {
  Platform platform = const LocalPlatform(),
  FileSystem fs = const LocalFileSystem(),
  bool throwOnFailure = false,
}) {
  assert(_osToPathStyle[platform.operatingSystem] == fs.path.style.name);
  try {
    workingDirectory ??= fs.currentDirectory.path;
  } on FileSystemException {
    // The `currentDirectory` getter can throw a FileSystemException for example
    // when the process doesn't have read/list permissions in each component of
    // the cwd path. In this case, fall back on '.'.
    workingDirectory ??= '.';
  }
  final Context context =
      Context(style: fs.path.style, current: workingDirectory);

  // TODO(goderbauer): refactor when github.com/google/platform.dart/issues/2
  //     is available.
  final String pathSeparator = platform.isWindows ? ';' : ':';

  List<String> extensions = <String>[];
  if (platform.isWindows && context.extension(executable).isEmpty) {
    extensions = platform.environment['PATHEXT']!.split(pathSeparator);
  }

  List<String> candidates = <String>[];
  List<String> searchPath;
  if (executable.contains(context.separator)) {
    // Deal with commands that specify a relative or absolute path differently.
    searchPath = <String>[workingDirectory];
  } else {
    searchPath = platform.environment['PATH']!.split(pathSeparator);
  }
  candidates = _getCandidatePaths(executable, searchPath, extensions, context);
  final List<String> foundCandidates = <String>[];
  for (final String path in candidates) {
    final File candidate = fs.file(path);
    final FileStat stat = candidate.statSync();
    // Only return files or links that exist.
    if (stat.type == FileSystemEntityType.notFound ||
        stat.type == FileSystemEntityType.directory) {
      continue;
    }

    // File exists, but we don't know if it's readable/executable yet.
    foundCandidates.add(candidate.path);

    const int isExecutable = 0x40;
    const int isReadable = 0x100;
    const int isExecutableAndReadable = isExecutable | isReadable;
    // Should only return files or links that are readable and executable by the
    // user.

    // On Windows it's not actually possible to only return files that are
    // readable, since Dart reports files that have had read permission removed
    // as being readable, but not checking for it is the same as checking for it
    // and finding it readable, so we use the same check here on all platforms,
    // so that if Dart ever gets fixed, it'll just work.
    if (stat.mode & isExecutableAndReadable == isExecutableAndReadable) {
      return path;
    }
  }
  if (throwOnFailure) {
    if (foundCandidates.isNotEmpty) {
      throw ProcessPackageExecutableNotFoundException(
        executable,
        message:
            'Found candidates, but lacked sufficient permissions to execute "$executable".',
        workingDirectory: workingDirectory,
        candidates: foundCandidates,
        searchPath: searchPath,
      );
    } else {
      throw ProcessPackageExecutableNotFoundException(
        executable,
        message: 'Failed to find "$executable" in the search path.',
        workingDirectory: workingDirectory,
        searchPath: searchPath,
      );
    }
  }
  return null;
}

/// Returns all possible combinations of `$searchPath\$command.$ext` for
/// `searchPath` in [searchPaths] and `ext` in [extensions].
///
/// If [extensions] is empty, it will just enumerate all
/// `$searchPath\$command`.
/// If [command] is an absolute path, it will just enumerate
/// `$command.$ext`.
List<String> _getCandidatePaths(
  String command,
  List<String> searchPaths,
  List<String> extensions,
  Context context,
) {
  final List<String> withExtensions = extensions.isNotEmpty
      ? extensions.map((String ext) => '$command$ext').toList()
      : <String>[command];
  if (context.isAbsolute(command)) {
    return withExtensions;
  }
  return searchPaths
      .map((String path) =>
          withExtensions.map((String command) => context.join(path, command)))
      .expand((Iterable<String> e) => e)
      .toList()
      .cast<String>();
}
