// 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:math' as math;

import 'package:status_file/canonical_status_file.dart';

class LintingError {
  final int lineNumber;
  final String message;
  LintingError(this.lineNumber, this.message);

  String toString() {
    return "Error at line $lineNumber: $message";
  }
}

/// Main function to check a status file for linting errors.
List<LintingError> lint(StatusFile file, {checkForDisjunctions = false}) {
  var errors = <LintingError>[];
  for (var section in file.sections) {
    errors
      ..addAll(lintCommentLinesInSection(section))
      ..addAll(lintAlphabeticalOrderingOfPaths(section))
      ..addAll(lintNormalizedSection(section))
      ..addAll(lintSectionEntryDuplicates(section));
    if (checkForDisjunctions) {
      errors.addAll(lintDisjunctionsInHeader(section));
    }
  }
  errors.addAll(lintSectionHeaderOrdering(file.sections));
  errors.addAll(lintSectionHeaderDuplicates(file.sections));
  return errors;
}

/// Checks for invalid comment lines in a section.
///
/// We do not allow the following:
///
/// [ ... ]
///
/// vm/test: Skip # description
/// # Some comment <-- invalid
/// ...
///
/// This function checks for such invalid comments.
Iterable<LintingError> lintCommentLinesInSection(StatusSection section) {
  if (section.lineNumber == -1) {
    // This is the default section, which also has the dart copyright notice.
    // Allow comment entries in the beginning of the file, until the first
    // status entry.
    var seenStatusEntry = false;
    var lintingErrors = <LintingError>[];
    for (var entry in section.entries) {
      seenStatusEntry = seenStatusEntry || entry is StatusEntry;
      if (seenStatusEntry && entry is CommentEntry) {
        lintingErrors.add(new LintingError(
            entry.lineNumber, "Comment is on a line by itself."));
      }
    }
    return lintingErrors;
  }
  return section.entries.whereType<CommentEntry>().map((entry) =>
      new LintingError(entry.lineNumber, "Comment is on a line by itself."));
}

/// Checks for disjunctions in headers. Disjunctions should be separated out.
///
/// Example:
/// [ $mode == debug || $mode == release ]
///
/// should not be allowed. The clauses should be refactored into own sections:
/// [ $mode == debug ]
/// ...
///
///
/// [ $mode == release ]
/// ...
///
/// Removing disjunctions will turn some sections into two or more sections with
/// the same status entries, but these will be much easier to process with our
/// tools.
Iterable<LintingError> lintDisjunctionsInHeader(StatusSection section) {
  if (section.condition.toString().contains("||")) {
    return [
      new LintingError(
          section.lineNumber,
          "Expression contains '||'. Please split the expression into multiple "
          "separate sections.")
    ];
  }
  return [];
}

/// Checks for correct ordering of test entries in sections. They should be
/// ordered alphabetically.
Iterable<LintingError> lintAlphabeticalOrderingOfPaths(StatusSection section) {
  var entries = section.entries
      .whereType<StatusEntry>()
      .map((entry) => (entry as StatusEntry).path)
      .toList();
  var sortedList = entries.toList()..sort((a, b) => a.compareTo(b));
  var witness = _findNotEqualWitness<String>(sortedList, entries);
  if (witness != null) {
    return [
      new LintingError(
          section.lineNumber,
          "Test paths are not alphabetically ordered in section. "
          "${witness.first} should come before ${witness.second}.")
    ];
  }
  return [];
}

/// Checks that each section expression have been normalized.
Iterable<LintingError> lintNormalizedSection(StatusSection section) {
  if (section.condition == null) return const [];
  var nonNormalized = section.condition.toString();
  var normalized = section.condition.normalize().toString();
  if (section.condition.toString() != normalized) {
    return [
      new LintingError(
          section.lineNumber,
          "Condition expression should be '$normalized' "
          "but was '$nonNormalized'.")
    ];
  }
  return const [];
}

/// Checks for duplicate section entries in the body of a section.
Iterable<LintingError> lintSectionEntryDuplicates(StatusSection section) {
  var errors = <LintingError>[];
  List<StatusEntry> statusEntries = section.entries
      .whereType<StatusEntry>()
      .toList();
  for (var i = 0; i < statusEntries.length; i++) {
    var entry = statusEntries[i];
    for (var j = i + 1; j < statusEntries.length; j++) {
      var otherEntry = statusEntries[j];
      if (entry.path == otherEntry.path &&
          _findNotEqualWitness(entry.expectations, otherEntry.expectations) ==
              null) {
        errors.add(new LintingError(
            section.lineNumber,
            "The status entry "
            "'${entry}' is duplicated on lines "
            "${entry.lineNumber} and ${otherEntry.lineNumber}."));
      }
    }
  }
  return errors;
}

/// Checks for incorrect ordering of section headers. Section headers should be
/// alphabetically ordered, except, when negation is used, it should be
/// lexicographically close to the none-negated one, but still come after.
///
/// [ $compiler == dart2js ] < [ $strong ]
/// [ $mode == debug ]       < [ $mode != debug ]
/// [ $strong ]              < [ ! $strong ]
///
/// A larger example could be the following:
///
/// [ $mode != debug ]
/// [ !strong ]
/// [ $mode == debug ]
/// [ strong ]
/// [ $compiler == dart2js ]
///
/// which should should become:
///
/// [ $compiler == dart2js ]
/// [ $mode == debug ]
/// [ $mode != debug ]
/// [ strong ]
/// [ !strong ]
///
Iterable<LintingError> lintSectionHeaderOrdering(List<StatusSection> sections) {
  var unsorted = sections.where((section) => section.lineNumber != -1).toList();
  var sorted = unsorted.toList()
    ..sort((a, b) => a.condition.compareTo(b.condition));
  var witness = _findNotEqualWitness<StatusSection>(sorted, unsorted);
  if (witness != null) {
    return [
      new LintingError(
          witness.second.lineNumber,
          "Section expressions are not correctly ordered in file. "
          "'${witness.first.condition}' on line ${witness.first.lineNumber} "
          "should come before '${witness.second.condition}' at line "
          "${witness.second.lineNumber}.")
    ];
  }
  return [];
}

/// Checks for duplicate section headers.
Iterable<LintingError> lintSectionHeaderDuplicates(
    List<StatusSection> sections) {
  var errors = <LintingError>[];
  var sorted = sections.where((section) => section.condition != null).toList()
    ..sort((a, b) => a.condition.compareTo(b.condition));
  for (var i = 1; i < sorted.length; i++) {
    var section = sorted[i];
    var previousSection = sorted[i - 1];
    if (section.condition != null &&
        previousSection.condition != null &&
        section.condition.compareTo(previousSection.condition) == 0) {
      errors.add(new LintingError(
          section.lineNumber,
          "The condition "
          "'${section.condition}' is duplicated on lines "
          "${previousSection.lineNumber} and ${section.lineNumber}."));
    }
  }
  return errors;
}

ListNotEqualWitness<T> _findNotEqualWitness<T>(List<T> first, List<T> second) {
  if (first.isEmpty && second.isEmpty) {
    return null;
  }
  for (var i = 0; i < math.max(first.length, second.length); i++) {
    if (i >= second.length) {
      return new ListNotEqualWitness(first[i], null);
    } else if (i >= first.length) {
      return new ListNotEqualWitness(null, second[i]);
    } else if (first[i] != second[i]) {
      return new ListNotEqualWitness(first[i], second[i]);
    }
  }
  return null;
}

class ListNotEqualWitness<T> {
  final T first;
  final T second;
  ListNotEqualWitness(this.first, this.second);
}
