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

  bool executableContainsSeparator = executable.contains(context.separator);

  // On Windows both '/' and '\' are valid path separators. Normalize to '\'
  // so that path operations are consistent.
  if (platform.isWindows && executable.contains('/')) {
    executableContainsSeparator = true;
    executable = context.normalize(executable);
  }

  // Deal with commands that specify a relative or absolute path differently.
  final List<String> searchPath = executableContainsSeparator
      ? <String>[workingDirectory]
      : platform.environment['PATH']!.split(pathSeparator);

  final List<String> 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>();
}
