// Copyright (c) 2016, 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:boolean_selector/boolean_selector.dart';
import 'package:collection/collection.dart';
import 'package:glob/glob.dart';
import 'package:path/path.dart' as p;
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';

import '../../backend/operating_system.dart';
import '../../backend/platform_selector.dart';
import '../../backend/test_platform.dart';
import '../../frontend/timeout.dart';
import '../../util/io.dart';
import '../../utils.dart';
import '../configuration.dart';
import '../configuration/suite.dart';
import 'reporters.dart';

/// A regular expression matching a Dart identifier.
///
/// This also matches a package name, since they must be Dart identifiers.
final identifierRegExp = new RegExp(r"[a-zA-Z_]\w*");

/// A regular expression matching allowed package names.
///
/// This allows dot-separated valid Dart identifiers. The dots are there for
/// compatibility with Google's internal Dart packages, but they may not be used
/// when publishing a package to pub.dartlang.org.
final _packageName = new RegExp(
    "^${identifierRegExp.pattern}(\\.${identifierRegExp.pattern})*\$");

/// Loads configuration information from a YAML file at [path].
///
/// If [global] is `true`, this restricts the configuration file to only rules
/// that are supported globally.
///
/// Throws a [FormatException] if the configuration is invalid, and a
/// [FileSystemException] if it can't be read.
Configuration load(String path, {bool global: false}) {
  var source = new File(path).readAsStringSync();
  var document = loadYamlNode(source, sourceUrl: p.toUri(path));

  if (document.value == null) return Configuration.empty;

  if (document is! Map) {
    throw new SourceSpanFormatException(
        "The configuration must be a YAML map.", document.span, source);
  }

  var loader = new _ConfigurationLoader(document, source, global: global);
  return loader.load();
}

/// A helper for [load] that tracks the YAML document.
class _ConfigurationLoader {
  /// The parsed configuration document.
  final YamlMap _document;

  /// The source string for [_document].
  ///
  /// Used for error reporting.
  final String _source;

  /// Whether this is parsing the global configuration file.
  final bool _global;

  /// Whether runner configuration is allowed at this level.
  final bool _runnerConfig;

  _ConfigurationLoader(this._document, this._source,
      {bool global: false, bool runnerConfig: true})
      : _global = global,
        _runnerConfig = runnerConfig;

  /// Loads the configuration in [_document].
  Configuration load() => _loadGlobalTestConfig()
      .merge(_loadLocalTestConfig())
      .merge(_loadGlobalRunnerConfig())
      .merge(_loadLocalRunnerConfig());

  /// Loads test configuration that's allowed in the global configuration file.
  Configuration _loadGlobalTestConfig() {
    var verboseTrace = _getBool("verbose_trace");
    var chainStackTraces = _getBool("chain_stack_traces");
    var foldStackFrames = _loadFoldedStackFrames();
    var jsTrace = _getBool("js_trace");

    var timeout = _parseValue("timeout", (value) => new Timeout.parse(value));

    var onPlatform = _getMap("on_platform",
        key: (keyNode) => _parseNode(keyNode, "on_platform key",
            (value) => new PlatformSelector.parse(value)),
        value: (valueNode) =>
            _nestedConfig(valueNode, "on_platform value", runnerConfig: false));

    var onOS = _getMap("on_os",
        key: (keyNode) {
          _validate(keyNode, "on_os key must be a string.",
              (value) => value is String);

          var os = OperatingSystem.find(keyNode.value);
          if (os != null) return os;

          throw new SourceSpanFormatException(
              'Invalid on_os key: No such operating system.',
              keyNode.span,
              _source);
        },
        value: (valueNode) => _nestedConfig(valueNode, "on_os value"));

    var presets = _getMap("presets",
        key: (keyNode) => _parseIdentifierLike(keyNode, "presets key"),
        value: (valueNode) => _nestedConfig(valueNode, "presets value"));

    var config = new Configuration(
            verboseTrace: verboseTrace,
            jsTrace: jsTrace,
            timeout: timeout,
            presets: presets,
            chainStackTraces: chainStackTraces,
            foldTraceExcept: foldStackFrames["except"],
            foldTraceOnly: foldStackFrames["only"])
        .merge(_extractPresets/*<PlatformSelector>*/(
            onPlatform, (map) => new Configuration(onPlatform: map)));

    var osConfig = onOS[currentOS];
    return osConfig == null ? config : config.merge(osConfig);
  }

  /// Loads test configuration that's not allowed in the global configuration
  /// file.
  ///
  /// If [_global] is `true`, this will error if there are any local test-level
  /// configuration fields.
  Configuration _loadLocalTestConfig() {
    if (_global) {
      _disallow("skip");
      _disallow("retry");
      _disallow("test_on");
      _disallow("add_tags");
      _disallow("tags");
      return Configuration.empty;
    }

    var skip = _getValue("skip", "boolean or string",
        (value) => value is bool || value is String);
    var skipReason;
    if (skip is String) {
      skipReason = skip;
      skip = true;
    }

    var testOn =
        _parseValue("test_on", (value) => new PlatformSelector.parse(value));

    var addTags = _getList(
        "add_tags", (tagNode) => _parseIdentifierLike(tagNode, "Tag name"));

    var tags = _getMap("tags",
        key: (keyNode) => _parseNode(
            keyNode, "tags key", (value) => new BooleanSelector.parse(value)),
        value: (valueNode) =>
            _nestedConfig(valueNode, "tag value", runnerConfig: false));

    var retry = _getNonNegativeInt("retry");

    return new Configuration(
            skip: skip,
            retry: retry,
            skipReason: skipReason,
            testOn: testOn,
            addTags: addTags)
        .merge(_extractPresets/*<BooleanSelector>*/(
            tags, (map) => new Configuration(tags: map)));
  }

  /// Loads runner configuration that's allowed in the global configuration
  /// file.
  ///
  /// If [_runnerConfig] is `false`, this will error if there are any
  /// runner-level configuration fields.
  Configuration _loadGlobalRunnerConfig() {
    if (!_runnerConfig) {
      _disallow("pause_after_load");
      _disallow("reporter");
      _disallow("concurrency");
      _disallow("names");
      _disallow("plain_names");
      _disallow("platforms");
      _disallow("add_presets");
      return Configuration.empty;
    }

    var pauseAfterLoad = _getBool("pause_after_load");
    var runSkipped = _getBool("run_skipped");

    var reporter = _getString("reporter");
    if (reporter != null && !allReporters.keys.contains(reporter)) {
      _error('Unknown reporter "$reporter".', "reporter");
    }

    var concurrency = _getInt("concurrency");

    var allPlatformIdentifiers =
        TestPlatform.all.map((platform) => platform.identifier).toSet();
    var platforms = _getList("platforms", (platformNode) {
      _validate(platformNode, "Platforms must be strings.",
          (value) => value is String);
      _validate(platformNode, 'Unknown platform "${platformNode.value}".',
          allPlatformIdentifiers.contains);

      return TestPlatform.find(platformNode.value);
    });

    var chosenPresets = _getList("add_presets",
        (presetNode) => _parseIdentifierLike(presetNode, "Preset name"));

    return new Configuration(
        pauseAfterLoad: pauseAfterLoad,
        runSkipped: runSkipped,
        reporter: reporter,
        concurrency: concurrency,
        platforms: platforms,
        chosenPresets: chosenPresets);
  }

  /// Loads runner configuration that's not allowed in the global configuration
  /// file.
  ///
  /// If [_runnerConfig] is `false` or if [_global] is `true`, this will error
  /// if there are any local test-level configuration fields.
  Configuration _loadLocalRunnerConfig() {
    if (!_runnerConfig || _global) {
      _disallow("pub_serve");
      _disallow("names");
      _disallow("plain_names");
      _disallow("paths");
      _disallow("filename");
      _disallow("include_tags");
      _disallow("exclude_tags");
      return Configuration.empty;
    }

    var pubServePort = _getInt("pub_serve");

    var patterns = _getList("names", (nameNode) {
      _validate(nameNode, "Names must be strings.", (value) => value is String);
      return _parseNode(nameNode, "name", (value) => new RegExp(value));
    })
      ..addAll(_getList("plain_names", (nameNode) {
        _validate(
            nameNode, "Names must be strings.", (value) => value is String);
        return nameNode.value;
      }));

    var paths = _getList("paths", (pathNode) {
      _validate(pathNode, "Paths must be strings.", (value) => value is String);
      _validate(pathNode, "Paths must be relative.", p.url.isRelative);

      return _parseNode(pathNode, "path", p.fromUri);
    });

    var filename = _parseValue("filename", (value) => new Glob(value));

    var includeTags = _parseBooleanSelector("include_tags");
    var excludeTags = _parseBooleanSelector("exclude_tags");

    return new Configuration(
        pubServePort: pubServePort,
        patterns: patterns,
        paths: paths,
        filename: filename,
        includeTags: includeTags,
        excludeTags: excludeTags);
  }

  /// Returns a map representation of the `fold_stack_frames` configuration.
  ///
  /// The key `except` will correspond to the list of packages to fold.
  /// The key `only` will correspond to the list of packages to keep in a
  /// test [Chain].
  Map<String, List<String>> _loadFoldedStackFrames() {
    var foldOptionSet = false;
    return _getMap("fold_stack_frames", key: (keyNode) {
      _validate(keyNode, "Must be a string", (value) => value is String);
      _validate(keyNode, 'Must be "only" or "except".',
          (value) => value == "only" || value == "except");

      if (foldOptionSet) {
        throw new SourceSpanFormatException(
            'Can only contain one of "only" or "except".',
            keyNode.span,
            _source);
      }
      foldOptionSet = true;
      return keyNode.value;
    }, value: (valueNode) {
      _validate(
          valueNode,
          "Folded packages must be strings.",
          (valueList) =>
              valueList is YamlList &&
              valueList.every((value) => value is String));

      _validate(
          valueNode,
          "Invalid package name.",
          (valueList) =>
              valueList.every((value) => _packageName.hasMatch(value)));

      return valueNode.value;
    });
  }

  /// Throws an exception with [message] if [test] returns `false` when passed
  /// [node]'s value.
  void _validate(YamlNode node, String message, bool test(value)) {
    if (test(node.value)) return;
    throw new SourceSpanFormatException(message, node.span, _source);
  }

  /// Returns the value of the node at [field].
  ///
  /// If [typeTest] returns `false` for that value, instead throws an error
  /// complaining that the field is not a [typeName].
  _getValue(String field, String typeName, bool typeTest(value)) {
    var value = _document[field];
    if (value == null || typeTest(value)) return value;
    _error("$field must be ${a(typeName)}.", field);
  }

  /// Returns the YAML node at [field].
  ///
  /// If [typeTest] returns `false` for that node's value, instead throws an
  /// error complaining that the field is not a [typeName].
  YamlNode _getNode(String field, String typeName, bool typeTest(value)) {
    var node = _document.nodes[field];
    if (node == null) return null;
    _validate(node, "$field must be ${a(typeName)}.", typeTest);
    return node;
  }

  /// Asserts that [field] is an int and returns its value.
  int _getInt(String field) => _getValue(field, "int", (value) => value is int);

  /// Asserts that [field] is a non-negative int and returns its value.
  int _getNonNegativeInt(String field) => _getValue(
      field, "non-negative int", (value) => value is int && value >= 0);

  /// Asserts that [field] is a boolean and returns its value.
  bool _getBool(String field) =>
      _getValue(field, "boolean", (value) => value is bool);

  /// Asserts that [field] is a string and returns its value.
  String _getString(String field) =>
      _getValue(field, "string", (value) => value is String);

  /// Asserts that [field] is a list and runs [forElement] for each element it
  /// contains.
  ///
  /// Returns a list of values returned by [forElement].
  List/*<T>*/ _getList/*<T>*/(
      String field,
      /*=T*/ forElement(YamlNode elementNode)) {
    var node = _getNode(field, "list", (value) => value is List) as YamlList;
    if (node == null) return [];
    return node.nodes.map(forElement).toList();
  }

  /// Asserts that [field] is a map and runs [key] and [value] for each pair.
  ///
  /// Returns a map with the keys and values returned by [key] and [value]. Each
  /// of these defaults to asserting that the value is a string.
  Map/*<K, V>*/ _getMap/*<K, V>*/(String field,
      {/*=K*/ key(YamlNode keyNode),
      /*=V*/ value(YamlNode valueNode)}) {
    var node = _getNode(field, "map", (value) => value is Map) as YamlMap;
    if (node == null) return {};

    key ??= (keyNode) {
      _validate(
          keyNode, "$field keys must be strings.", (value) => value is String);

      return keyNode.value as dynamic/*=K*/;
    };

    value ??= (valueNode) {
      _validate(valueNode, "$field values must be strings.",
          (value) => value is String);

      return valueNode.value as dynamic/*=V*/;
    };

    return mapMap(node.nodes,
        key: (keyNode, _) => key(keyNode),
        value: (_, valueNode) => value(valueNode));
  }

  /// Verifies that [node]'s value is an optionally hyphenated Dart identifier,
  /// and returns it
  String _parseIdentifierLike(YamlNode node, String name) {
    _validate(node, "$name must be a string.", (value) => value is String);
    _validate(node, "$name must be an (optionally hyphenated) Dart identifier.",
        (value) => value.contains(anchoredHyphenatedIdentifier));
    return node.value;
  }

  /// Parses [node]'s value as a boolean selector.
  BooleanSelector _parseBooleanSelector(String name) =>
      _parseValue(name, (value) => new BooleanSelector.parse(value));

  /// Asserts that [node] is a string, passes its value to [parse], and returns
  /// the result.
  ///
  /// If [parse] throws a [FormatException], it's wrapped to include [node]'s
  /// span.
  /*=T*/ _parseNode/*<T>*/(
      YamlNode node,
      String name,
      /*=T*/ parse(String value)) {
    _validate(node, "$name must be a string.", (value) => value is String);

    try {
      return parse(node.value);
    } on FormatException catch (error) {
      throw new SourceSpanFormatException(
          'Invalid $name: ${error.message}', node.span, _source);
    }
  }

  /// Asserts that [field] is a string, passes it to [parse], and returns the
  /// result.
  ///
  /// If [parse] throws a [FormatException], it's wrapped to include [field]'s
  /// span.
  /*=T*/ _parseValue/*<T>*/(String field, /*=T*/ parse(String value)) {
    var node = _document.nodes[field];
    if (node == null) return null;
    return _parseNode(node, field, parse);
  }

  /// Parses a nested configuration document.
  ///
  /// [name] is the name of the field, which is used for error-handling.
  /// [runnerConfig] controls whether runner configuration is allowed in the
  /// nested configuration. It defaults to [_runnerConfig].
  Configuration _nestedConfig(YamlNode node, String name, {bool runnerConfig}) {
    if (node == null || node.value == null) return Configuration.empty;

    _validate(node, "$name must be a map.", (value) => value is Map);
    var loader = new _ConfigurationLoader(node, _source,
        global: _global, runnerConfig: runnerConfig ?? _runnerConfig);
    return loader.load();
  }

  /// Takes a map that contains [Configuration]s and extracts any
  /// preset-specific configuration into a parent [Configuration].
  ///
  /// This is needed because parameters to [new Configuration] such as
  /// `onPlatform` take maps to [SuiteConfiguration]s. [SuiteConfiguration]
  /// doesn't support preset-specific configuration, so this extracts the preset
  /// logic into a parent [Configuration], leaving only maps to
  /// [SuiteConfiguration]s. The [create] function is used to construct
  /// [Configuration]s from the resolved maps.
  Configuration _extractPresets/*<T>*/(Map/*<T, Configuration>*/ map,
      Configuration create(Map/*<T, SuiteConfiguration>*/ map)) {
    if (map.isEmpty) return Configuration.empty;

    var base = /*<T, SuiteConfiguration>*/ {};
    var presets = /*<String, Map<T, SuiteConfiguration>>*/ {};
    map.forEach((key, config) {
      base[key] = config.suiteDefaults;
      config.presets.forEach((preset, presetConfig) {
        presets.putIfAbsent(preset, () => {})[key] = presetConfig.suiteDefaults;
      });
    });

    if (presets.isEmpty) {
      return base.isEmpty ? Configuration.empty : create(base);
    } else {
      var newPresets =
          mapMap/*<String, Map<T, SuiteConfiguration>, String, Configuration>*/(
              presets,
              value: (_, map) => create(map));
      return create(base).change(presets: newPresets);
    }
  }

  /// Throws an error if a field named [field] exists at this level.
  void _disallow(String field) {
    if (!_document.containsKey(field)) return;

    throw new SourceSpanFormatException(
        "$field isn't supported here.",
        // We need the key as a [YamlNode] to get its span.
        _document.nodes.keys.firstWhere((key) => key.value == field).span,
        _source);
  }

  /// Throws a [SourceSpanFormatException] with [message] about [field].
  void _error(String message, String field) {
    throw new SourceSpanFormatException(
        message, _document.nodes[field].span, _source);
  }
}
