// 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:path/path.dart' as p;

import 'environment.dart';
import 'expectation.dart';
import 'status_file.dart';
import 'src/expression.dart';

/// Matches the header that begins a new section, like:
///
///     [ $compiler == dart2js && $minified ]
final RegExp _sectionPattern = new RegExp(r"^\[(.+?)\]");

/// Matches an entry that defines the status for a path in the current section,
/// like:
///
///     some/path/to/some_test: Pass || Fail
final RegExp _entryPattern = new RegExp(r"^([^:#]+):([^#]+)(#.*)?");

/// Matches an issue number in a comment, like:
///
///     blah_test: Fail # Issue 1234
///                       ^^^^
final RegExp _issuePattern = new RegExp(r"[Ii]ssue (\d+)");

/// Matches a comment and indented comment, like:
///
///     < white space > #
final RegExp _commentPattern = new RegExp(r"^(\s*)#");

/// A parsed status file, which describes how a collection of tests are
/// expected to behave under various configurations and conditions.
///
/// Each status file is made of a series of sections. Each section begins with
/// a header, followed by a series of entries. A header is enclosed in square
/// brackets and contains a Boolean expression. That expression is evaluated in
/// an environment. If it evaluates to true, then the entries after the header
/// take effect.
///
/// Each entry is a glob-like file path followed by a colon and then a
/// comma-separated list of [Expectation]s. The path is a regular expression
/// which may match one or more file or directory paths. If it matches a
/// directory path, it is considered to match all files in that directory or
/// (recursively) its subdirectories.
///
/// The intent is that status files will not have stand-alone comment lines. All
/// comments should be at the end of a single entry, and apply to that entry
/// only.
///
/// Until this is true for all status files, this program handles stand-alone
/// comment lines as follows:
///
/// 1) One or more comment lines immediately preceding a section header if there
/// is a linebreak from the previous section. Comment sections are added
/// directly to a section and are not entries.
/// 2) Comment lines anywhere else. These should be carefully removed when
/// found.
///
/// The reason for this distinction is to allow comments to be above sections,
/// without including these when lexicographically ordering section entries.
///
/// Entries may also appear before any section header, are considered to belong
/// to a default section, which always applies.
class StatusFile {
  final String path;
  final List<StatusSection> sections = [];

  int _lineCount = 1;

  /// Constructor for creating a new [StatusFile]. Will not create the default
  /// section that status files have.
  StatusFile(this.path);

  /// Reads and parses the status file at [path].
  ///
  /// Throws a [SyntaxError] if the file could not be parsed.
  StatusFile.read(this.path) {
    _parse(new File(path).readAsLinesSync());
  }

  /// Parses lines of strings coming from a status file at [path].
  ///
  /// Throws a [SyntaxError] if the file could not be parsed.
  StatusFile.parse(this.path, List<String> lines) {
    _parse(lines.map((line) => line.trim()).toList());
  }

  void _parse(List<String> lines) {
    // We define a few helper functions that are used when parsing.

    /// Checks if [currentLine] is a comment and returns the first regular
    /// expression match, or null otherwise.
    Match commentEntryMatch(int currentLine) {
      if (currentLine < 1 || currentLine > lines.length) {
        return null;
      }
      return _commentPattern.firstMatch(lines[currentLine - 1]);
    }

    /// Finds a section header on [currentLine] if the line is in range of
    /// [lines].
    Match sectionHeaderMatch(int currentLine) {
      if (currentLine < 1 || currentLine > lines.length) {
        return null;
      }
      return _sectionPattern.firstMatch(lines[currentLine - 1]);
    }

    /// Checks if a line has a break from the previous section. A break is an
    /// empty line. It searches recursively until it find a break or a test
    /// entry.
    bool hasBreakFromPreviousSection(int currentLine) {
      if (currentLine <= 1) {
        return true;
      }

      var line = lines[currentLine - 1];
      if (line.isEmpty) {
        return true;
      }

      if (line.startsWith("#")) {
        return hasBreakFromPreviousSection(currentLine - 1);
      }

      return false;
    }

    /// Checks if comment on [currentLine] belongs to the next section.
    bool commentBelongsToNextSectionHeader(int currentLine) {
      if (currentLine >= lines.length ||
          commentEntryMatch(currentLine) == null) {
        return false;
      }
      return sectionHeaderMatch(currentLine + 1) != null ||
          commentBelongsToNextSectionHeader(currentLine + 1);
    }

    // List of comments added before the next section's header.
    List<Entry> sectionHeaderComments = [];

    // Parse file comments
    var lastEmptyLine = 0;
    for (; _lineCount <= lines.length; _lineCount++) {
      var line = lines[_lineCount - 1];
      if (!line.startsWith("#") && line.isNotEmpty) {
        break;
      }
      if (line.isEmpty) {
        sectionHeaderComments.add(new EmptyEntry(_lineCount));
        lastEmptyLine = _lineCount;
      } else {
        sectionHeaderComments
            .add(new CommentEntry(_lineCount, new Comment(line)));
      }
    }

    var implicitSectionHeaderComments = sectionHeaderComments;
    var entries = <Entry>[];
    if (lastEmptyLine > 0 && sectionHeaderMatch(_lineCount) != null) {
      // Comments after the last empty line belong to the next section's header.
      // The empty line is not added to the section header, because it will be
      // added to the section's entries.
      implicitSectionHeaderComments =
          implicitSectionHeaderComments.sublist(0, lastEmptyLine - 1);
      entries.add(sectionHeaderComments[lastEmptyLine - 1]);
      sectionHeaderComments = sectionHeaderComments.sublist(lastEmptyLine);
    } else {
      // Reset section header comments.
      sectionHeaderComments = [];
    }

    // The current section whose rules are being parsed. Initialized to an
    // implicit section that matches everything.
    StatusSection section =
        new StatusSection(null, -1, implicitSectionHeaderComments);
    section.entries.addAll(entries);
    sections.add(section);

    for (; _lineCount <= lines.length; _lineCount++) {
      var line = lines[_lineCount - 1];

      fail(String message, [List<String> errors]) {
        throw new SyntaxError(_shortPath, _lineCount, line, message, errors);
      }

      // If it is an empty line
      if (line.isEmpty) {
        section.entries.add(new EmptyEntry(_lineCount));
        continue;
      }

      // See if we are starting a new section.
      var match = _sectionPattern.firstMatch(line);
      if (match != null) {
        try {
          var condition = Expression.parse(match[1].trim());
          section =
              new StatusSection(condition, _lineCount, sectionHeaderComments);
          sections.add(section);
          // Reset section header comments.
          sectionHeaderComments = [];
        } on FormatException {
          fail("Status expression syntax error");
        }
        continue;
      }

      // If it is in a new entry we should add to the current section.
      match = _entryPattern.firstMatch(line);
      if (match != null) {
        var path = match[1].trim();
        var expectations = <Expectation>[];
        // split expectations
        match[2].split(",").forEach((name) {
          try {
            expectations.add(Expectation.find(name.trim()));
          } on ArgumentError {
            fail('Unrecognized test expectation "${name.trim()}"');
          }
        });
        if (match[3] == null) {
          section.entries
              .add(new StatusEntry(path, _lineCount, expectations, null));
        } else {
          section.entries.add(new StatusEntry(
              path, _lineCount, expectations, new Comment(match[3])));
        }
        continue;
      }

      // If it is a comment, we have to find if it belongs with the current
      // section or the next section
      match = _commentPattern.firstMatch(line);
      if (match != null) {
        var commentEntry = new CommentEntry(_lineCount, new Comment(line));
        if (hasBreakFromPreviousSection(_lineCount) &&
            commentBelongsToNextSectionHeader(_lineCount)) {
          sectionHeaderComments.add(commentEntry);
        } else {
          section.entries.add(commentEntry);
        }
        continue;
      }

      fail("Unrecognized input");
    }

    // There are no comment entries in [sectionHeaderComments], because of the
    // check for [commentBelongsToSectionHeader].
    assert(sectionHeaderComments.length == 0);
  }

  bool get isEmpty => sections.length == 1 && sections[0].isEmpty();

  /// Validates that the variables and values used in all of the section
  /// condition expressions are defined in [environment].
  ///
  /// Throws a [SyntaxError] on the first found error.
  void validate(Environment environment) {
    for (var section in sections) {
      if (section.condition == null) continue;

      var errors = <String>[];
      section.condition.validate(environment, errors);

      if (errors.isNotEmpty) {
        var s = errors.length > 1 ? "s" : "";
        throw new SyntaxError(_shortPath, section.lineNumber,
            "[ ${section.condition} ]", 'Validation error$s', errors);
      }
    }
  }

  /// Gets the path to this status file relative to the Dart repo root.
  String get _shortPath {
    var repoRoot = p.fromUri(Platform.script.resolve('../../../'));
    return p.normalize(p.relative(path, from: repoRoot));
  }

  /// Returns the status file as a string. This preserves comments and gives a
  /// "canonical" rendering of the status file that can be saved back to disc.
  String toString() {
    var buffer = new StringBuffer();
    sections.forEach(buffer.write);
    return buffer.toString();
  }
}

/// One section in a status file.
///
/// Contains the condition from the header that begins the section, then all of
/// the entries within the section.
class StatusSection {
  /// The expression that determines when this section is applied.
  ///
  /// May be `null` for paths that appear before any section header in the file.
  /// In that case, the section always applies.
  final Expression condition;

  /// The one-based line number where the section appears in the file.
  final int lineNumber;

  /// Collection of all comment and status line entries.
  final List<Entry> entries = [];
  final List<Entry> sectionHeaderComments;

  /// Returns true if this section should apply in the given [environment].
  bool isEnabled(Environment environment) =>
      condition == null || condition.evaluate(environment);

  bool isEmpty() => !entries.any((entry) => entry is StatusEntry);

  StatusSection(this.condition, this.lineNumber, this.sectionHeaderComments);

  @override
  String toString() {
    var buffer = new StringBuffer();
    sectionHeaderComments.forEach(buffer.writeln);
    if (condition != null) {
      buffer.writeln("[ ${condition} ]");
    }
    entries.forEach(buffer.writeln);
    return buffer.toString();
  }
}

class Comment {
  final String _comment;

  Comment(this._comment);

  /// Returns the issue number embedded in [comment] or `null` if there is none.
  int issueNumber(String comment) {
    var match = _issuePattern.firstMatch(comment);
    if (match == null) return null;
    return int.parse(match[1]);
  }

  @override
  String toString() {
    return _comment;
  }
}

abstract class Entry {
  /// The one-based line number where the entry appears in the file.
  final int lineNumber;
  Entry(this.lineNumber);
}

class EmptyEntry extends Entry {
  EmptyEntry(lineNumber) : super(lineNumber);

  @override
  String toString() {
    return "";
  }
}

class CommentEntry extends Entry {
  final Comment comment;
  CommentEntry(lineNumber, this.comment) : super(lineNumber);

  @override
  String toString() {
    return comment.toString();
  }
}

/// Describes the test status of the file or files at a given path.
class StatusEntry extends Entry {
  final String path;
  final List<Expectation> expectations;
  final Comment comment;

  StatusEntry(this.path, lineNumber, this.expectations, this.comment)
      : super(lineNumber);

  @override
  String toString() {
    return comment == null
        ? "$path: ${expectations.join(', ')}"
        : "$path: ${expectations.join(', ')} $comment";
  }
}
