// Copyright (c) 2017, 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 'dart:io';

import 'package:io/io.dart';
import 'package:path/path.dart' as p;
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';

/// User-provided settings for invoking an executable.
class ExecutableSettings {
  /// Additional arguments to pass to the executable.
  final List<String> arguments;

  /// The path to the executable on Linux.
  ///
  /// This may be an absolute path or a basename, in which case it will be
  /// looked up on the system path. It may not be relative.
  final String _linuxExecutable;

  /// The path to the executable on Mac OS.
  ///
  /// This may be an absolute path or a basename, in which case it will be
  /// looked up on the system path. It may not be relative.
  final String _macOSExecutable;

  /// The path to the executable on Windows.
  ///
  /// This may be an absolute path; a basename, in which case it will be looked
  /// up on the system path; or a relative path, in which case it will be looked
  /// up relative to the paths in the `LOCALAPPDATA`, `PROGRAMFILES`, and
  /// `PROGRAMFILES(X64)` environment variables.
  final String _windowsExecutable;

  /// The path to the executable for the current operating system.
  String get executable {
    if (Platform.isMacOS) return _macOSExecutable;
    if (!Platform.isWindows) return _linuxExecutable;
    if (p.isAbsolute(_windowsExecutable)) return _windowsExecutable;
    if (p.basename(_windowsExecutable) == _windowsExecutable) {
      return _windowsExecutable;
    }

    var prefixes = [
      Platform.environment['LOCALAPPDATA'],
      Platform.environment['PROGRAMFILES'],
      Platform.environment['PROGRAMFILES(X86)']
    ];

    for (var prefix in prefixes) {
      if (prefix == null) continue;

      var path = p.join(prefix, _windowsExecutable);
      if (File(path).existsSync()) return path;
    }

    // If we can't find a path that works, return one that doesn't. This will
    // cause an "executable not found" error to surface.
    return p.join(
        prefixes.firstWhere((prefix) => prefix != null, orElse: () => '.'),
        _windowsExecutable);
  }

  /// Whether to invoke the browser in headless mode.
  ///
  /// This is currently only supported by Chrome.
  bool get headless => _headless ?? true;
  final bool _headless;

  /// Parses settings from a user-provided YAML mapping.
  factory ExecutableSettings.parse(YamlMap settings) {
    List<String> arguments;
    var argumentsNode = settings.nodes['arguments'];
    if (argumentsNode != null) {
      var value = argumentsNode.value;
      if (value is String) {
        try {
          arguments = shellSplit(value);
        } on FormatException catch (error) {
          throw SourceSpanFormatException(error.message, argumentsNode.span);
        }
      } else {
        throw SourceSpanFormatException(
            'Must be a string.', argumentsNode.span);
      }
    }

    String linuxExecutable;
    String macOSExecutable;
    String windowsExecutable;
    var executableNode = settings.nodes['executable'];
    if (executableNode != null) {
      var value = executableNode.value;
      if (value is String) {
        // Don't check this on Windows because people may want to set relative
        // paths in their global config.
        if (!Platform.isWindows) {
          _assertNotRelative(executableNode as YamlScalar);
        }

        linuxExecutable = value;
        macOSExecutable = value;
        windowsExecutable = value;
      } else if (executableNode is YamlMap) {
        linuxExecutable = _getExecutable(executableNode.nodes['linux']);
        macOSExecutable = _getExecutable(executableNode.nodes['mac_os']);
        windowsExecutable = _getExecutable(executableNode.nodes['windows'],
            allowRelative: true);
      } else {
        throw SourceSpanFormatException(
            'Must be a map or a string.', executableNode.span);
      }
    }

    var headless = true;
    var headlessNode = settings.nodes['headless'];
    if (headlessNode != null) {
      var value = headlessNode.value;
      if (value is bool) {
        headless = value;
      } else {
        throw SourceSpanFormatException(
            'Must be a boolean.', headlessNode.span);
      }
    }

    return ExecutableSettings(
        arguments: arguments,
        linuxExecutable: linuxExecutable,
        macOSExecutable: macOSExecutable,
        windowsExecutable: windowsExecutable,
        headless: headless);
  }

  /// Asserts that [executableNode] is a string or `null` and returns it.
  ///
  /// If [allowRelative] is `false` (the default), asserts that the value isn't
  /// a relative path.
  static String _getExecutable(YamlNode executableNode,
      {bool allowRelative = false}) {
    if (executableNode == null || executableNode.value == null) return null;
    if (executableNode.value is! String) {
      throw SourceSpanFormatException('Must be a string.', executableNode.span);
    }
    if (!allowRelative) _assertNotRelative(executableNode as YamlScalar);
    return executableNode.value as String;
  }

  /// Throws a [SourceSpanFormatException] if [executableNode]'s value is a
  /// relative POSIX path that's not just a plain basename.
  ///
  /// We loop up basenames on the PATH and we can resolve absolute paths, but we
  /// have no way of interpreting relative paths.
  static void _assertNotRelative(YamlScalar executableNode) {
    var executable = executableNode.value as String;
    if (!p.posix.isRelative(executable)) return;
    if (p.posix.basename(executable) == executable) return;

    throw SourceSpanFormatException(
        'Linux and Mac OS executables may not be relative paths.',
        executableNode.span);
  }

  ExecutableSettings(
      {Iterable<String> arguments,
      String linuxExecutable,
      String macOSExecutable,
      String windowsExecutable,
      bool headless})
      : arguments = arguments == null ? const [] : List.unmodifiable(arguments),
        _linuxExecutable = linuxExecutable,
        _macOSExecutable = macOSExecutable,
        _windowsExecutable = windowsExecutable,
        _headless = headless;

  /// Merges [this] with [other], with [other]'s settings taking priority.
  ExecutableSettings merge(ExecutableSettings other) => ExecutableSettings(
      arguments: arguments.toList()..addAll(other.arguments),
      headless: other._headless ?? _headless,
      linuxExecutable: other._linuxExecutable ?? _linuxExecutable,
      macOSExecutable: other._macOSExecutable ?? _macOSExecutable,
      windowsExecutable: other._windowsExecutable ?? _windowsExecutable);
}
