// 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 'package:status_file/environment.dart';

import 'configuration.dart';

typedef String _LookUpFunction(TestConfiguration configuration);
typedef bool _BoolLookUpFunction(TestConfiguration configuration);

// TODO(29756): Instead of synthesized negated variables like "unchecked",
// consider adding support for "!" to status expressions.
final _variables = {
  "analyzer": new _Variable.bool((c) => c.compiler == Compiler.dart2analyzer),
  "analyzer_use_fasta_parser":
      new _Variable.bool((c) => c.useAnalyzerFastaParser),
  "arch": new _Variable((c) => c.architecture.name, Architecture.names),
  "browser": new _Variable.bool((c) => c.runtime.isBrowser),
  "builder_tag": new _Variable((c) => c.builderTag ?? "", const []),
  "checked": new _Variable.bool((c) => c.isChecked),
  "compiler": new _Variable((c) => c.compiler.name, Compiler.names),
  "csp": new _Variable.bool((c) => c.isCsp),
  "enable_asserts": new _Variable.bool((c) => c.useEnableAsserts),
  "fasta": new _Variable.bool((c) => c.usesFasta),
  "host_checked": new _Variable.bool((c) => c.isHostChecked),
  "host_unchecked": new _Variable.bool((c) => !c.isHostChecked),
  "hot_reload": new _Variable.bool((c) => c.hotReload),
  "hot_reload_rollback": new _Variable.bool((c) => c.hotReloadRollback),
  "ie": new _Variable.bool((c) => c.runtime.isIE),
  "jscl": new _Variable.bool((c) => c.runtime.isJSCommandLine),
  "minified": new _Variable.bool((c) => c.isMinified),
  "mode": new _Variable((c) => c.mode.name, Mode.names),
  "no_preview_dart_2": new _Variable.bool((c) => c.noPreviewDart2),
  "preview_dart_2": new _Variable.bool((c) => !c.noPreviewDart2),
  "runtime": new _Variable(_runtimeName, _runtimeNames),
  "spec_parser": new _Variable.bool((c) => c.compiler == Compiler.specParser),
  "strong": new _Variable.bool((c) => !c.noPreviewDart2),
  "system": new _Variable(_systemName, _systemNames),
  "use_sdk": new _Variable.bool((c) => c.useSdk)
};

/// Gets the name of the runtime as it appears in status files.
String _runtimeName(TestConfiguration configuration) {
  // TODO(rnystrom): Handle "ff" being used as the name for firefox. We don't
  // want to make the Runtime itself use that as the name because it appears
  // elsewhere in test.dart and we want those other places to show "firefox".
  if (configuration.runtime == Runtime.firefox) return 'ff';

  return configuration.runtime.name;
}

List<String> _runtimeNames = ['ff', 'drt']..addAll(Runtime.names);

/// Gets the name of the runtime as it appears in status files.
String _systemName(TestConfiguration configuration) {
  // Because we are getting rid of status files, we don't want to change all
  // of them to say "win" instead of "windows" and "mac" instead of "macos"
  if (configuration.system == System.win) return 'windows';
  if (configuration.system == System.mac) return 'macos';

  return configuration.system.name;
}

List<String> _systemNames = ['windows', 'macos']..addAll(System.names);

/// Defines the variables that are available for use inside a status file
/// section header.
///
/// These mostly map to command line arguments with the same name, though this
/// is only a subset of the full set of command line arguments.
class ConfigurationEnvironment implements Environment {
  /// The configuration where variable data is found.
  final TestConfiguration _configuration;

  ConfigurationEnvironment(this._configuration);

  /// Validates that the variable with [name] exists and can be compared
  /// against [value].
  ///
  /// If any errors are found, adds them to [errors].
  void validate(String name, String value, List<String> errors) {
    var variable = _variables[name];
    if (variable == null) {
      errors.add('Unknown variable "$name".');
      return;
    }

    // The "builder_tag" variable doesn't have an enumerated set of values.
    if (variable.allowedValues.isEmpty) return;

    if (!variable.allowedValues.contains(value)) {
      errors.add(
          'Variable "$name" cannot have value "$value". Allowed values are:\n' +
              variable.allowedValues.join(', ') +
              '.');
    }
  }

  /// Looks up the value of the variable with [name].
  String lookUp(String name) {
    var variable = _variables[name];
    if (variable == null) {
      // This shouldn't happen since we validate variables before evaluating
      // expressions.
      throw new ArgumentError('Unknown variable "$variable".');
    }

    return variable.lookUp(_configuration);
  }
}

// TODO(rnystrom): There's some overlap between these and _Option in
// options.dart. Unify?
/// Describes a variable name whose value can be tested in a status file.
///
/// Each variable is an enumerated string type that only accepts a limited range
/// of values. Each instance of this class defines one variable, the values it
/// permits, and the logic needed to look up the variable's value from a
/// [TestConfiguration]
class _Variable {
  final _LookUpFunction _lookUp;
  final List<String> allowedValues;

  _Variable(this._lookUp, Iterable<String> allowed)
      : allowedValues = allowed.toList();

  /// Creates a Boolean variable with allowed values "true" and "false".
  _Variable.bool(_BoolLookUpFunction lookUp)
      : _lookUp = ((configuration) => lookUp(configuration).toString()),
        allowedValues = const ["true", "false"];

  String lookUp(TestConfiguration configuration) => _lookUp(configuration);
}
