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

import 'configuration.dart';
import 'environment.dart';

/// Tracks the [Expectation]s associated with a set of file paths.
///
/// For any given file path, returns the expected test results for that file.
/// A set can be loaded from a collection of status files. A file path may
/// exist in multiple files (or even multiple sections within the file). When
/// that happens, all of the expectations of every entry are combined.
class ExpectationSet {
  /// Reads the expectations defined by the status files at [statusFilePaths]
  /// when in [configuration].
  static ExpectationSet read(
      List<String> statusFilePaths, Configuration configuration) {
    try {
      var environment = new ConfigurationEnvironment(configuration);
      var expectations = new ExpectationSet._();
      for (var path in statusFilePaths) {
        var file = new StatusFile.read(path);
        file.validate(environment);
        for (var section in file.sections) {
          if (section.isEnabled(environment)) {
            for (var entry in section.entries) {
              expectations.addEntry(entry);
            }
          }
        }
      }

      return expectations;
    } on SyntaxError catch (error) {
      stderr.writeln(error.toString());
      exit(1);

      throw "unreachable";
    }
  }

  // Only create one copy of each Set<Expectation>.
  // We just use .toString as a key, so we may make a few
  // sets that only differ in their toString element order.
  static Map<String, Set<Expectation>> _cachedSets = {};

  Map<String, Set<Expectation>> _map = {};
  Map<String, List<RegExp>> _keyToRegExps;

  /// Create a TestExpectations object. See the [expectations] method
  /// for an explanation of matching.
  ExpectationSet._();

  /// Add [entry] to the set of expectations.
  void addEntry(StatusEntry entry) {
    // Once we have started using the expectations we cannot add more
    // rules.
    if (_keyToRegExps != null) {
      throw new StateError("Cannot add entries after it is already in use.");
    }

    _map
        .putIfAbsent(entry.path, () => new Set<Expectation>())
        .addAll(entry.expectations);
  }

  /// Get the expectations for the test at [path].
  ///
  /// For every (key, expectation) pair, matches the key with the file name.
  /// Returns the union of the expectations for all the keys that match.
  ///
  /// Normal matching splits the key and the filename into path components and
  /// checks that the anchored regular expression "^$keyComponent\$" matches
  /// the corresponding filename component.
  Set<Expectation> expectations(String path) {
    var result = new Set<Expectation>();
    var parts = path.split('/');

    // Create mapping from keys to list of RegExps once and for all.
    _preprocessForMatching();

    _map.forEach((key, expectations) {
      var regExps = _keyToRegExps[key];
      if (regExps.length > parts.length) return;

      for (var i = 0; i < regExps.length; i++) {
        if (!regExps[i].hasMatch(parts[i])) return;
      }

      // If all components of the status file key matches the filename
      // add the expectations to the result.
      result.addAll(expectations);
    });

    // If no expectations were found the expectation is that the test
    // passes.
    if (result.isEmpty) {
      result.add(Expectation.pass);
    }
    return _cachedSets.putIfAbsent(result.toString(), () => result);
  }

  /// Preprocesses the expectations for matching against filenames. Generates
  /// lists of regular expressions once and for all for each key.
  void _preprocessForMatching() {
    if (_keyToRegExps != null) return;

    _keyToRegExps = {};
    var regExpCache = <String, RegExp>{};

    _map.forEach((key, expectations) {
      if (_keyToRegExps[key] != null) return;
      var splitKey = key.split('/');
      var regExps = new List<RegExp>(splitKey.length);

      for (var i = 0; i < splitKey.length; i++) {
        var component = splitKey[i];
        var regExp = regExpCache.putIfAbsent(component,
            () => new RegExp("^${splitKey[i]}\$".replaceAll('*', '.*')));
        regExps[i] = regExp;
      }

      _keyToRegExps[key] = regExps;
    });
  }
}
