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

import '../environment.dart';

/// A parsed Boolean expression AST.
abstract class Expression implements Comparable<Expression> {
  /// An expression that always evaluates to true.
  ///
  /// Used for the section at the top of a status file with no expression.
  static const Expression always = _AlwaysExpression();

  /// Parses Boolean expressions in a .status file for Dart.
  ///
  /// The grammar is:
  ///
  ///     expression := or
  ///     or         := and ( "||" and )*
  ///     and        := primary ( "&&" primary )*
  ///     primary    := "$" identifier ( "==" | "!=" ) identifier |
  ///                   "!"? "$" identifier |
  ///                   "(" expression ")"
  ///     identifier := regex "\w+"
  ///
  /// Expressions evaluate as expected, with values of variables found in an
  /// environment passed to the evaluator.
  static Expression parse(String expression) =>
      _ExpressionParser(expression).parse();

  const Expression();

  /// Validates that this expression does not contain any invalid uses of
  /// variables.
  ///
  /// Ensures that any variable names are known and that any literal values are
  /// allowed for their corresponding variable. If an invalid variable or value
  /// is found, adds appropriate error messages to [errors].
  void validate(Environment environment, List<String> errors);

  /// Evaluates the expression where all variables are defined by the given
  /// [environment].
  bool evaluate(Environment environment);

  /// Produce a "normalized" version of this expression.
  ///
  /// This removes any redundant computation and orders subexpressions in a
  /// well-defined way such that two expressions with the same tree structure
  /// and operands should result in equivalent expressions. It:
  ///
  /// * Simplifies comparisons against boolean literals "true" and "false" to
  ///   the equivalent bare variable forms.
  /// * Sorts the operands to a series of logic operators in a well-defined way.
  ///   (We are free to do this because status expressions are side-effect free
  ///   and don't need to short-circuit).
  /// * Removes duplicate operands to logic operators.
  ///
  /// This does not try to produce a *minimal* expression that calculates the
  /// same truth values as the original expression.
  Expression normalize();

  /// Computes a relative ordering between two expressions or returns zero if
  /// they are exactly identical.
  ///
  /// This is useful for things like sorting lists of expressions or
  /// normalizing a list of subexpressions. The rough logic is that higher
  /// precedence and alphabetically lower expressions come first.
  @override
  int compareTo(Expression other) {
    var comparison = _typeComparison.compareTo(other._typeComparison);
    if (comparison != 0) return comparison;

    // They must be the same type.
    return _compareToMyType(other);
  }

  int _compareToMyType(covariant Expression other);

  /// The "precedence" of each expression type when comparing them using
  /// `compareTo()`. Expressions whose type is lower compare earlier.
  int get _typeComparison;
}

/// Keyword token strings.
class _Token {
  static const leftParen = "(";
  static const rightParen = ")";
  static const dollar = r"$";
  static const equals = "==";
  static const notEqual = "!=";
  static const and = "&&";
  static const or = "||";
  static const not = "!";
}

/// A reference to a variable.
class Variable {
  final String name;

  Variable(this.name);

  String lookup(Environment environment) {
    var value = environment.lookUp(name);
    if (value == null) {
      throw Exception("Could not find '$name' in environment "
          "while evaluating status file expression.");
    }

    // Explicitly stringify all values so that things like:
    //
    //     $strong == true
    //
    // work correctly even though "true" is treated as a string here.
    // TODO(rnystrom): Is there a cleaner/safer way to do this?
    return value.toString();
  }
}

/// An expression that always evaluates to true.
///
/// Used for the implicit section at the top of a status file that always
/// matches.
class _AlwaysExpression extends Expression {
  const _AlwaysExpression();

  @override
  int _compareToMyType(covariant _AlwaysExpression other) => 0;

  @override
  int get _typeComparison => 0;

  @override
  bool evaluate(Environment environment) => true;

  @override
  Expression normalize() => this;

  @override
  void validate(Environment environment, List<String> errors) {}
}

/// Tests whether a given variable is or is not equal some literal value, as in:
/// ```
/// $variable == someValue
/// ```
/// Negate the result if [negate] is true.
class ComparisonExpression extends Expression {
  final Variable left;
  final String right;
  final bool negate;

  ComparisonExpression(this.left, this.right, this.negate);

  @override
  void validate(Environment environment, List<String> errors) {
    environment.validate(left.name, right, errors);
  }

  @override
  bool evaluate(Environment environment) {
    return negate != (left.lookup(environment) == right);
  }

  @override
  Expression normalize() {
    // Replace Boolean comparisons with a straight variable expression.
    if (right == "true") {
      return VariableExpression(left, negate: negate);
    } else if (right == "false") {
      return VariableExpression(left, negate: !negate);
    } else {
      return this;
    }
  }

  @override
  int _compareToMyType(ComparisonExpression other) {
    if (left.name != other.left.name) {
      return left.name.compareTo(other.left.name);
    }

    if (right != other.right) {
      return right.compareTo(other.right);
    }

    return _compareBool(negate, other.negate);
  }

  // Comparisons come before variables so that "$compiler == ..." and
  // "$runtime == ..." appear on the left in status expressions.
  @override
  int get _typeComparison => 1;

  @override
  String toString() => "\$${left.name} ${negate ? '!=' : '=='} $right";
}

/// A reference to a variable defined in the environment. The expression
/// evaluates to true if the variable's stringified value is "true".
/// ```
///     $variable
/// ```
/// is equivalent to
/// ```
///     $variable == true
/// ```
/// Negates result if [negate] is true, so
/// ```
///     !$variable
/// ```
/// is equivalent to
/// ```
///     $variable != true
/// ```
class VariableExpression extends Expression {
  final Variable variable;
  final bool negate;

  VariableExpression(this.variable, {this.negate = false});

  @override
  void validate(Environment environment, List<String> errors) {
    // It must be a Boolean, so it should allow either Boolean value.
    environment.validate(variable.name, "true", errors);
  }

  @override
  bool evaluate(Environment environment) =>
      negate != (variable.lookup(environment) == "true");

  /// Variable expressions are fine as they are.
  @override
  Expression normalize() => this;

  @override
  int _compareToMyType(VariableExpression other) {
    if (variable.name != other.variable.name) {
      return variable.name.compareTo(other.variable.name);
    }

    return _compareBool(negate, other.negate);
  }

  @override
  int get _typeComparison => 2;

  @override
  String toString() => "${negate ? "!" : ""}\$${variable.name}";
}

/// A logical `||` or `&&` expression.
class LogicExpression extends Expression {
  /// The operator, `||` or `&&`.
  final String op;

  final List<Expression> operands;

  LogicExpression(this.op, this.operands);

  LogicExpression.and(this.operands) : op = _Token.and;
  LogicExpression.or(this.operands) : op = _Token.or;

  bool get isAnd => op == _Token.and;
  bool get isOr => op == _Token.or;

  @override
  void validate(Environment environment, List<String> errors) {
    for (var operand in operands) {
      operand.validate(environment, errors);
    }
  }

  @override
  bool evaluate(Environment environment) {
    if (op == _Token.and) {
      return operands.every((operand) => operand.evaluate(environment));
    } else {
      return operands.any((operand) => operand.evaluate(environment));
    }
  }

  @override
  LogicExpression normalize() {
    // Normalize the order of the clauses. Since there is no short-circuiting,
    // a || b means the same as b || a. Picking a standard order lets us
    // identify and collapse identical expressions that only differ by clause
    // order.

    // Recurse into the operands, sort them, and remove duplicates.
    var normalized = LogicExpression(
            op, operands.map((operand) => operand.normalize()).toList())
        .operands;
    normalized = flatten(normalized);
    var ordered = SplayTreeSet<Expression>.from(normalized).toList();
    return LogicExpression(op, ordered);
  }

  List<Expression> flatten(List<Expression> operands) {
    var newOperands = <Expression>[];
    for (var operand in operands) {
      if (operand is LogicExpression && operand.op == op) {
        newOperands.addAll(operand.operands);
      } else {
        newOperands.add(operand);
      }
    }
    return newOperands;
  }

  @override
  int _compareToMyType(LogicExpression other) {
    // Put "&&" before "||".
    if (op != other.op) return op == _Token.and ? -1 : 1;

    // Lexicographically compare the operands.
    var length = math.max(operands.length, other.operands.length);
    for (var i = 0; i < length; i++) {
      if (i >= operands.length) return -1;
      if (i >= other.operands.length) return 1;

      var comparison = operands[i].compareTo(other.operands[i]);
      if (comparison != 0) return comparison;
    }

    return 0;
  }

  @override
  int get _typeComparison => 3;

  @override
  String toString() {
    String parenthesize(Expression operand) {
      var result = operand.toString();
      if (isAnd && operand is LogicExpression && operand.isOr) {
        result = "($result)";
      }

      return result;
    }

    return operands.map(parenthesize).join(" $op ");
  }
}

/// Parser for Boolean expressions in a .status file for Dart.
class _ExpressionParser {
  final _Scanner _scanner;

  _ExpressionParser(String expression) : _scanner = _Scanner(expression);

  Expression parse() {
    var expression = _parseOr();

    // Should consume entire string.
    if (_scanner.hasMore) {
      throw FormatException("Unexpected input after expression");
    }

    return expression;
  }

  Expression _parseOr() {
    var operands = [_parseAnd()];
    while (_scanner.match(_Token.or)) {
      operands.add(_parseAnd());
    }

    if (operands.length == 1) return operands.single;

    return LogicExpression(_Token.or, operands);
  }

  Expression _parseAnd() {
    var operands = [_parsePrimary()];
    while (_scanner.match(_Token.and)) {
      operands.add(_parsePrimary());
    }

    if (operands.length == 1) return operands.single;

    return LogicExpression(_Token.and, operands);
  }

  Expression _parsePrimary() {
    // TODO(mkroghj,rnystrom) If DNF is enforced, the need to parse parenthesis
    // should go away. Remove this when all section headers has dnf'ed.
    if (_scanner.match(_Token.leftParen)) {
      var value = _parseOr();
      if (!_scanner.match(_Token.rightParen)) {
        throw FormatException("Missing right parenthesis in expression");
      }

      return value;
    }

    var negate = false;
    if (_scanner.match(_Token.not)) {
      negate = true;
    }

    // The only atomic booleans are of the form $variable == value or
    // of the form $variable.
    if (!_scanner.match(_Token.dollar)) {
      throw FormatException(
          "Expected \$ in expression, got ${_scanner.current}");
    }

    if (!_scanner.isIdentifier) {
      throw FormatException(
          "Expected identifier in expression, got ${_scanner.current}");
    }

    var left = Variable(_scanner.current!);
    _scanner.advance();

    if (!negate &&
        (_scanner.current == _Token.equals ||
            _scanner.current == _Token.notEqual)) {
      var isNotEquals = _scanner.advance() == _Token.notEqual;

      if (!_scanner.isIdentifier) {
        throw FormatException(
            "Expected value in expression, got ${_scanner.current}");
      }

      var right = _scanner.advance()!;
      return ComparisonExpression(left, right, isNotEquals);
    } else {
      return VariableExpression(left, negate: negate);
    }
  }
}

/// An iterator that allows peeking at the current token.
class _Scanner {
  /// Tokens are "(", ")", "$", "&&", "||", "!", ==", "!=", and (maximal) \w+.
  static final _testPattern = RegExp(r"^(?:[()$\w\s]|&&|\|\||==|!=?)+$");
  static final _tokenPattern = RegExp(r"[()$]|&&|\|\||==|!=?|\w+");

  /// Pattern that recognizes identifier tokens.
  ///
  /// Only checks the first character, since no non-identifier token can start
  /// with a word character.
  static final _identifierPattern = RegExp(r"^\w");

  /// The token strings being iterated.
  final Iterator<String> tokenIterator;

  String? current;

  _Scanner(String expression) : tokenIterator = tokenize(expression).iterator {
    advance();
  }

  static List<String> tokenize(String expression) {
    if (!_testPattern.hasMatch(expression)) {
      throw FormatException("Syntax error in '$expression'");
    }

    return _tokenPattern
        .allMatches(expression)
        .map((match) => match[0]!)
        .toList();
  }

  bool get hasMore => current != null;

  /// Returns `true` if the current token is an identifier.
  // All non-identifier tokens are one or two characters,
  // so a longer token must be an identifier.
  bool get isIdentifier =>
      current!.length > 2 || _identifierPattern.hasMatch(current!);

  /// If the current token is [token], consumes it and returns `true`.
  bool match(String token) {
    if (!hasMore || current != token) return false;

    advance();
    return true;
  }

  /// Consumes the current token and returns it.
  String? advance() {
    var previous = current;
    current = tokenIterator.moveNext() ? tokenIterator.current : null;
    return previous;
  }
}

int _compareBool(bool a, bool b) {
  if (a == b) return 0;
  if (a) return 1;
  return -1;
}
