// Copyright (c) 2013, 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.

library polymer_expressions.eval;

import 'dart:async';
import 'dart:collection';

import 'package:observe/observe.dart';
import 'package:smoke/smoke.dart' as smoke;

import 'async.dart';
import 'expression.dart';
import 'filter.dart';
import 'visitor.dart';

final _BINARY_OPERATORS = {
  '+':   (a, b) => a + b,
  '-':   (a, b) => a - b,
  '*':   (a, b) => a * b,
  '/':   (a, b) => a / b,
  '%':   (a, b) => a % b,
  '==':  (a, b) => a == b,
  '!=':  (a, b) => a != b,
  '===': (a, b) => identical(a, b),
  '!==': (a, b) => !identical(a, b),
  '>':   (a, b) => a > b,
  '>=':  (a, b) => a >= b,
  '<':   (a, b) => a < b,
  '<=':  (a, b) => a <= b,
  '||':  (a, b) => a || b,
  '&&':  (a, b) => a && b,
  '|':   (a, f) {
    if (f is Transformer) return f.forward(a);
    if (f is Filter) return f(a);
    throw new EvalException("Filters must be a one-argument function.");
  }
};

final _UNARY_OPERATORS = {
  '+': (a) => a,
  '-': (a) => -a,
  '!': (a) => !a,
};

final _BOOLEAN_OPERATORS = ['!', '||', '&&'];

/**
 * Evaluation [expr] in the context of [scope].
 */
Object eval(Expression expr, Scope scope) => new EvalVisitor(scope).visit(expr);

/**
 * Returns an [ExpressionObserver] that evaluates [expr] in the context of
 * scope] and listens for any changes on [Observable] values that are
 * returned from sub-expressions. When a value changes the expression is
 * reevaluated and the new result is sent to the [onUpdate] stream of the
 * [ExpressionObsserver].
 */
ExpressionObserver observe(Expression expr, Scope scope) {
  var observer = new ObserverBuilder().visit(expr);
  return observer;
}

/**
 * Causes [expr] to be reevaluated a returns it's value.
 */
Object update(ExpressionObserver expr, Scope scope, {skipChanges: false}) {
  new Updater(scope, skipChanges).visit(expr);
  return expr.currentValue;
}

/**
 * Assign [value] to the variable or field referenced by [expr] in the context
 * of [scope].
 *
 * [expr] must be an /assignable/ expression, it must not contain
 * operators or function invocations, and any index operations must use a
 * literal index.
 */
Object assign(Expression expr, Object value, Scope scope,
    {bool checkAssignability: true}) {

  Expression expression;
  var property;
  bool isIndex = false;
  var filters = <Expression>[]; // reversed order for assignment

  while (expr is BinaryOperator) {
    BinaryOperator op = expr;
    if (op.operator != '|') {
      break;
    }
    filters.add(op.right);
    expr = op.left;
  }

  if (expr is Identifier) {
    expression = empty();
    property = expr.value;
  } else if (expr is Index) {
    expression = expr.receiver;
    property = expr.argument;
    isIndex = true;
  } else if (expr is Getter) {
    expression = expr.receiver;
    property = expr.name;
  } else {
    if (checkAssignability) {
      throw new EvalException("Expression is not assignable: $expr");
    }
    return null;
  }

  // transform the values backwards through the filters
  for (var filterExpr in filters) {
    var filter = eval(filterExpr, scope);
    if (filter is! Transformer) {
      if (checkAssignability) {
        throw new EvalException("filter must implement Transformer to be "
            "assignable: $filterExpr");
      } else {
        return null;
      }
    }
    value = filter.reverse(value);
  }
  // evaluate the receiver
  var o = eval(expression, scope);

  // can't assign to a property on a null LHS object. Silently fail.
  if (o == null) return null;

  if (isIndex) {
    var index = eval(property, scope);
    o[index] = value;
  } else {
    smoke.write(o, smoke.nameToSymbol(property), value);
  }
  return value;
}


/**
 * A scope in polymer expressions that can map names to objects. Scopes contain
 * a set of named variables and a unique model object. The scope structure
 * is then used to lookup names using the `[]` operator. The lookup first
 * searches for the name in local variables, then in global variables,
 * and then finally looks up the name as a property in the model.
 */
abstract class Scope implements Indexable<String, Object> {
  Scope._();

  /** Create a scope containing a [model] and all of [variables]. */
  factory Scope({Object model, Map<String, Object> variables}) {
    var scope = new _ModelScope(model);
    return variables == null ? scope
        : new _GlobalsScope(new Map<String, Object>.from(variables), scope);
  }

  /** Return the unique model in this scope. */
  Object get model;

  /**
   * Lookup the value of [name] in the current scope. If [name] is 'this', then
   * we return the [model]. For any other name, this finds the first variable
   * matching [name] or, if none exists, the property [name] in the [model].
   */
  Object operator [](String name);

  operator []=(String name, Object value) {
    throw new UnsupportedError('[]= is not supported in Scope.');
  }

  /**
   * Returns whether [name] is defined in [model], that is, a lookup
   * would not find a variable with that name, but there is a non-null model
   * where we can look it up as a property.
   */
  bool _isModelProperty(String name);

  /** Create a new scope extending this scope with an additional variable. */
  Scope childScope(String name, Object value) =>
      new _LocalVariableScope(name, value, this);
}

/**
 * A scope that looks up names in a model object. This kind of scope has no
 * parent scope because all our lookup operations stop when we reach the model
 * object. Any variables added in scope or global variables are added as child
 * scopes.
 */
class _ModelScope extends Scope {
  final Object model;

  _ModelScope(this.model) : super._();

  Object operator[](String name) {
    if (name == 'this') return model;
    var symbol = smoke.nameToSymbol(name);
    if (model == null || symbol == null) {
      throw new EvalException("variable '$name' not found");
    }
    return _convert(smoke.read(model, symbol));
  }

  Object _isModelProperty(String name) => name != 'this';

  String toString() => "[model: $model]";
}

/**
 * A scope that holds a reference to a single variable. Polymer expressions
 * introduce variables to the scope one at a time. Each time a variable is
 * added, a new [_LocalVariableScope] is created.
 */
class _LocalVariableScope extends Scope {
  final Scope parent;
  final String varName;
  // TODO(sigmund,justinfagnani): make this @observable?
  final Object value;

  _LocalVariableScope(this.varName, this.value, this.parent) : super._() {
    if (varName == 'this') {
      throw new EvalException("'this' cannot be used as a variable name.");
    }
  }

  Object get model => parent != null ? parent.model : null;

  Object operator[](String name) {
    if (varName == name) return _convert(value);
    if (parent != null) return parent[name];
    throw new EvalException("variable '$name' not found");
  }

  bool _isModelProperty(String name) {
    if (varName == name) return false;
    return parent == null ? false : parent._isModelProperty(name);
  }

  String toString() => "$parent > [local: $varName]";
}

/** A scope that holds a reference to a global variables. */
class _GlobalsScope extends Scope {
  final _ModelScope parent;
  final Map<String, Object> variables;

  _GlobalsScope(this.variables, this.parent) : super._() {
    if (variables.containsKey('this')) {
      throw new EvalException("'this' cannot be used as a variable name.");
    }
  }

  Object get model => parent != null ? parent.model : null;

  Object operator[](String name) {
    if (variables.containsKey(name)) return _convert(variables[name]);
    if (parent != null) return parent[name];
    throw new EvalException("variable '$name' not found");
  }

  bool _isModelProperty(String name) {
    if (variables.containsKey(name)) return false;
    return parent == null ? false : parent._isModelProperty(name);
  }

  String toString() => "$parent > [global: ${variables.keys}]";
}

Object _convert(v) => v is Stream ? new StreamBinding(v) : v;

abstract class ExpressionObserver<E extends Expression> implements Expression {
  final E _expr;
  ExpressionObserver _parent;

  StreamSubscription _subscription;
  Object _value;

  StreamController _controller = new StreamController.broadcast();
  Stream get onUpdate => _controller.stream;

  ExpressionObserver(this._expr);

  Expression get expression => _expr;

  Object get currentValue => _value;

  update(Scope scope) => _updateSelf(scope);

  _updateSelf(Scope scope) {}

  _invalidate(Scope scope) {
    _observe(scope, false);
    if (_parent != null) {
      _parent._invalidate(scope);
    }
  }

  _unobserve() {
    if (_subscription != null) {
      _subscription.cancel();
      _subscription = null;
    }
  }

  _observe(Scope scope, skipChanges) {
    _unobserve();

    var _oldValue = _value;

    // evaluate
    _updateSelf(scope);

    if (!skipChanges && !identical(_value, _oldValue)) {
      _controller.add(_value);
    }
  }

  String toString() => _expr.toString();
}

class Updater extends RecursiveVisitor {
  final Scope scope;
  final bool skipChanges;

  Updater(this.scope, [this.skipChanges = false]);

  visitExpression(ExpressionObserver e) {
    e._observe(scope, skipChanges);
  }
}

class Closer extends RecursiveVisitor {
  static final _instance = new Closer._();
  factory Closer() => _instance;
  Closer._();

  visitExpression(ExpressionObserver e) {
    e._unobserve();
  }
}

class EvalVisitor extends Visitor {
  final Scope scope;

  EvalVisitor(this.scope);

  visitEmptyExpression(EmptyExpression e) => scope.model;

  visitParenthesizedExpression(ParenthesizedExpression e) => visit(e.child);

  visitGetter(Getter g) {
    var receiver = visit(g.receiver);
    if (receiver == null) return null;
    var symbol = smoke.nameToSymbol(g.name);
    return smoke.read(receiver, symbol);
  }

  visitIndex(Index i) {
    var receiver = visit(i.receiver);
    if (receiver == null) return null;
    var key = visit(i.argument);
    return receiver[key];
  }

  visitInvoke(Invoke i) {
    var receiver = visit(i.receiver);
    if (receiver == null) return null;
    var args = (i.arguments == null)
        ? null
        : i.arguments.map(visit).toList(growable: false);

    if (i.method == null) {
      assert(receiver is Function);
      return Function.apply(receiver, args);
    }

    var symbol = smoke.nameToSymbol(i.method);
    return smoke.invoke(receiver, symbol, args);
  }

  visitLiteral(Literal l) => l.value;

  visitListLiteral(ListLiteral l) => l.items.map(visit).toList();

  visitMapLiteral(MapLiteral l) {
    var map = {};
    for (var entry in l.entries) {
      var key = visit(entry.key);
      var value = visit(entry.entryValue);
      map[key] = value;
    }
    return map;
  }

  visitMapLiteralEntry(MapLiteralEntry e) =>
      throw new UnsupportedError("should never be called");

  visitIdentifier(Identifier i) => scope[i.value];

  visitBinaryOperator(BinaryOperator o) {
    var operator = o.operator;
    var left = visit(o.left);
    var right = visit(o.right);

    var f = _BINARY_OPERATORS[operator];
    if (operator == '&&' || operator == '||') {
      // TODO: short-circuit
      return f(_toBool(left), _toBool(right));
    } else if (operator == '==' || operator == '!=') {
      return f(left, right);
    } else if (left == null || right == null) {
      return null;
    }
    return f(left, right);
  }

  visitUnaryOperator(UnaryOperator o) {
    var expr = visit(o.child);
    var f = _UNARY_OPERATORS[o.operator];
    if (o.operator == '!') {
      return f(_toBool(expr));
    }
    return (expr == null) ? null : f(expr);
  }

  visitTernaryOperator(TernaryOperator o) =>
      visit(o.condition) == true ? visit(o.trueExpr) : visit(o.falseExpr);

  visitInExpression(InExpression i) =>
      throw new UnsupportedError("can't eval an 'in' expression");

  visitAsExpression(AsExpression i) =>
      throw new UnsupportedError("can't eval an 'as' expression");
}

class ObserverBuilder extends Visitor {
  final Queue parents = new Queue();

  ObserverBuilder();

  visitEmptyExpression(EmptyExpression e) => new EmptyObserver(e);

  visitParenthesizedExpression(ParenthesizedExpression e) => visit(e.child);

  visitGetter(Getter g) {
    var receiver = visit(g.receiver);
    var getter = new GetterObserver(g, receiver);
    receiver._parent = getter;
    return getter;
  }

  visitIndex(Index i) {
    var receiver = visit(i.receiver);
    var arg = visit(i.argument);
    var index =  new IndexObserver(i, receiver, arg);
    receiver._parent = index;
    arg._parent = index;
    return index;
  }

  visitInvoke(Invoke i) {
    var receiver = visit(i.receiver);
    var args = (i.arguments == null)
        ? null
        : i.arguments.map(visit).toList(growable: false);
    var invoke =  new InvokeObserver(i, receiver, args);
    receiver._parent = invoke;
    if (args != null) args.forEach((a) => a._parent = invoke);
    return invoke;
  }

  visitLiteral(Literal l) => new LiteralObserver(l);

  visitListLiteral(ListLiteral l) {
    var items = l.items.map(visit).toList(growable: false);
    var list = new ListLiteralObserver(l, items);
    items.forEach((e) => e._parent = list);
    return list;
  }

  visitMapLiteral(MapLiteral l) {
    var entries = l.entries.map(visit).toList(growable: false);
    var map = new MapLiteralObserver(l, entries);
    entries.forEach((e) => e._parent = map);
    return map;
  }

  visitMapLiteralEntry(MapLiteralEntry e) {
    var key = visit(e.key);
    var value = visit(e.entryValue);
    var entry = new MapLiteralEntryObserver(e, key, value);
    key._parent = entry;
    value._parent = entry;
    return entry;
  }

  visitIdentifier(Identifier i) => new IdentifierObserver(i);

  visitBinaryOperator(BinaryOperator o) {
    var left = visit(o.left);
    var right = visit(o.right);
    var binary = new BinaryObserver(o, left, right);
    left._parent = binary;
    right._parent = binary;
    return binary;
  }

  visitUnaryOperator(UnaryOperator o) {
    var expr = visit(o.child);
    var unary = new UnaryObserver(o, expr);
    expr._parent = unary;
    return unary;
  }

  visitTernaryOperator(TernaryOperator o) {
    var condition = visit(o.condition);
    var trueExpr = visit(o.trueExpr);
    var falseExpr = visit(o.falseExpr);
    var ternary = new TernaryObserver(o, condition, trueExpr, falseExpr);
    condition._parent = ternary;
    trueExpr._parent = ternary;
    falseExpr._parent = ternary;
    return ternary;
  }

  visitInExpression(InExpression i) {
    throw new UnsupportedError("can't eval an 'in' expression");
  }

  visitAsExpression(AsExpression i) {
    throw new UnsupportedError("can't eval an 'as' expression");
  }
}

class EmptyObserver extends ExpressionObserver<EmptyExpression>
    implements EmptyExpression {

  EmptyObserver(EmptyExpression value) : super(value);

  _updateSelf(Scope scope) {
    _value = scope.model;
    // TODO(justin): listen for scope.model changes?
  }

  accept(Visitor v) => v.visitEmptyExpression(this);
}

class LiteralObserver extends ExpressionObserver<Literal> implements Literal {

  LiteralObserver(Literal value) : super(value);

  dynamic get value => _expr.value;

  _updateSelf(Scope scope) {
    _value = _expr.value;
  }

  accept(Visitor v) => v.visitLiteral(this);
}

class ListLiteralObserver extends ExpressionObserver<ListLiteral>
    implements ListLiteral {

  final List<ExpressionObserver> items;

  ListLiteralObserver(ListLiteral value, this.items) : super(value);

  _updateSelf(Scope scope) {
    _value = items.map((i) => i._value).toList();
  }

  accept(Visitor v) => v.visitListLiteral(this);
}

class MapLiteralObserver extends ExpressionObserver<MapLiteral>
    implements MapLiteral {

  final List<MapLiteralEntryObserver> entries;

  MapLiteralObserver(MapLiteral value, this.entries) : super(value);

  _updateSelf(Scope scope) {
    _value = entries.fold(new Map(),
        (m, e) => m..[e.key._value] = e.entryValue._value);
  }

  accept(Visitor v) => v.visitMapLiteral(this);
}

class MapLiteralEntryObserver extends ExpressionObserver<MapLiteralEntry>
    implements MapLiteralEntry {

  final LiteralObserver key;
  final ExpressionObserver entryValue;

  MapLiteralEntryObserver(MapLiteralEntry value, this.key, this.entryValue)
      : super(value);

  accept(Visitor v) => v.visitMapLiteralEntry(this);
}

class IdentifierObserver extends ExpressionObserver<Identifier>
    implements Identifier {

  IdentifierObserver(Identifier value) : super(value);

  String get value => _expr.value;

  _updateSelf(Scope scope) {
    _value = scope[value];
    if (!scope._isModelProperty(value)) return;
    var model = scope.model;
    if (model is! Observable) return;
    var symbol = smoke.nameToSymbol(value);
    _subscription = (model as Observable).changes.listen((changes) {
      if (changes.any((c) => c is PropertyChangeRecord && c.name == symbol)) {
        _invalidate(scope);
      }
    });
  }

  accept(Visitor v) => v.visitIdentifier(this);
}

class ParenthesizedObserver extends ExpressionObserver<ParenthesizedExpression>
    implements ParenthesizedExpression {
  final ExpressionObserver child;

  ParenthesizedObserver(ParenthesizedExpression expr, this.child) : super(expr);


  _updateSelf(Scope scope) {
    _value = child._value;
  }

  accept(Visitor v) => v.visitParenthesizedExpression(this);
}

class UnaryObserver extends ExpressionObserver<UnaryOperator>
    implements UnaryOperator {
  final ExpressionObserver child;

  UnaryObserver(UnaryOperator expr, this.child) : super(expr);

  String get operator => _expr.operator;

  _updateSelf(Scope scope) {
    var f = _UNARY_OPERATORS[_expr.operator];
    if (operator == '!') {
      _value = f(_toBool(child._value));
    } else {
      _value = (child._value == null) ? null : f(child._value);
    }
  }

  accept(Visitor v) => v.visitUnaryOperator(this);
}

class BinaryObserver extends ExpressionObserver<BinaryOperator>
    implements BinaryOperator {

  final ExpressionObserver left;
  final ExpressionObserver right;

  BinaryObserver(BinaryOperator expr, this.left, this.right)
      : super(expr);

  String get operator => _expr.operator;

  _updateSelf(Scope scope) {
    var f = _BINARY_OPERATORS[operator];
    if (operator == '&&' || operator == '||') {
      _value = f(_toBool(left._value), _toBool(right._value));
    } else if (operator == '==' || operator == '!=') {
      _value = f(left._value, right._value);
    } else if (left._value == null || right._value == null) {
      _value = null;
    } else {
      if (operator == '|' && left._value is ObservableList) {
        _subscription = (left._value as ObservableList).listChanges
            .listen((_) => _invalidate(scope));
      }
      _value = f(left._value, right._value);
    }
  }

  accept(Visitor v) => v.visitBinaryOperator(this);

}

class TernaryObserver extends ExpressionObserver<TernaryOperator>
    implements TernaryOperator {

  final ExpressionObserver condition;
  final ExpressionObserver trueExpr;
  final ExpressionObserver falseExpr;

  TernaryObserver(TernaryOperator expr, this.condition, this.trueExpr,
      this.falseExpr) : super(expr);

  _updateSelf(Scope scope) {
    _value = _toBool(condition._value) ? trueExpr._value : falseExpr._value;
  }

  accept(Visitor v) => v.visitTernaryOperator(this);

}

class GetterObserver extends ExpressionObserver<Getter> implements Getter {
  final ExpressionObserver receiver;

  GetterObserver(Expression expr, this.receiver) : super(expr);

  String get name => _expr.name;

  _updateSelf(Scope scope) {
    var receiverValue = receiver._value;
    if (receiverValue == null) {
      _value = null;
      return;
    }
    var symbol = smoke.nameToSymbol(_expr.name);
    _value = smoke.read(receiverValue, symbol);

    if (receiverValue is Observable) {
      _subscription = (receiverValue as Observable).changes.listen((changes) {
        if (changes.any((c) => c is PropertyChangeRecord && c.name == symbol)) {
          _invalidate(scope);
        }
      });
    }
  }

  accept(Visitor v) => v.visitGetter(this);
}

class IndexObserver extends ExpressionObserver<Index> implements Index {
  final ExpressionObserver receiver;
  final ExpressionObserver argument;

  IndexObserver(Expression expr, this.receiver, this.argument) : super(expr);

  _updateSelf(Scope scope) {
    var receiverValue = receiver._value;
    if (receiverValue == null) {
      _value = null;
      return;
    }
    var key = argument._value;
    _value = receiverValue[key];

    if (receiverValue is ObservableList) {
      _subscription = (receiverValue as ObservableList).listChanges
          .listen((changes) {
        if (changes.any((c) => c.indexChanged(key))) _invalidate(scope);
      });
    } else if (receiverValue is Observable) {
      _subscription = (receiverValue as Observable).changes.listen((changes) {
        if (changes.any((c) => c is MapChangeRecord && c.key == key)) {
          _invalidate(scope);
        }
      });
    }
  }

  accept(Visitor v) => v.visitIndex(this);
}

class InvokeObserver extends ExpressionObserver<Invoke> implements Invoke {
  final ExpressionObserver receiver;
  final List<ExpressionObserver> arguments;

  InvokeObserver(Expression expr, this.receiver, this.arguments)
      : super(expr) {
    assert(arguments != null);
  }

  String get method => _expr.method;

  _updateSelf(Scope scope) {
    var args = arguments.map((a) => a._value).toList();
    var receiverValue = receiver._value;
    if (receiverValue == null) {
      _value = null;
      return;
    }
    if (_expr.method == null) {
      // top-level function or model method
      // TODO(justin): listen to model changes to see if the method has
      // changed? listen to the scope to see if the top-level method has
      // changed?
      assert(receiverValue is Function);
      _value = _convert(Function.apply(receiverValue, args));
    } else {
      var symbol = smoke.nameToSymbol(_expr.method);
      _value = smoke.invoke(receiverValue, symbol, args);

      if (receiverValue is Observable) {
        _subscription = (receiverValue as Observable).changes.listen(
            (List<ChangeRecord> changes) {
              if (changes.any(
                  (c) => c is PropertyChangeRecord && c.name == symbol)) {
                _invalidate(scope);
              }
            });
      }
    }
  }

  accept(Visitor v) => v.visitInvoke(this);
}

_toBool(v) => (v == null) ? false : v;

class EvalException implements Exception {
  final String message;
  EvalException(this.message);
  String toString() => "EvalException: $message";
}
