// 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> {
  /// 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) =>
      new _ExpressionParser(expression).parse();

  /// 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.
  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 new 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();
  }
}

/// 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);

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

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

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

  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.
  int get _typeComparison => 0;

  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});

  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);
  }

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

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

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

    return _compareBool(negate, other.negate);
  }

  int get _typeComparison => 1;

  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;

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

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

  Expression 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 = new LogicExpression(
            op, operands.map((operand) => operand.normalize()).toList())
        .operands;
    normalized = flatten(normalized);
    var ordered = new SplayTreeSet<Expression>.from(normalized).toList();
    return new 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;
  }

  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;
  }

  int get _typeComparison => 2;

  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 = new _Scanner(expression);

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

    // Should consume entire string.
    if (_scanner.hasMore) {
      throw new 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 new 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 new 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 new 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 new FormatException(
          "Expected \$ in expression, got ${_scanner.current}");
    }

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

    var left = new 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 new FormatException(
            "Expected value in expression, got ${_scanner.current}");
      }

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

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