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

import 'dart:html';
import 'package:mdv/mdv.dart' as mdv;
import 'package:observe/observe.dart' show toObservable;
import 'package:unittest/html_config.dart';
import 'package:unittest/unittest.dart';
import 'mdv_test_utils.dart';

main() {
  mdv.initialize();
  useHtmlConfiguration();
  group('Custom Element Bindings', customElementBindingsTest);
}

customElementBindingsTest() {
  var testDiv;

  setUp(() {
    document.body.append(testDiv = new DivElement());
  });

  tearDown(() {
    testDiv.remove();
    testDiv = null;
  });

  createTestHtml(s) {
    var div = new DivElement();
    div.setInnerHtml(s, treeSanitizer: new NullTreeSanitizer());
    testDiv.append(div);

    for (var node in div.queryAll('*')) {
      if (node.isTemplate) TemplateElement.decorate(node);
    }

    return div;
  }


  observeTest('override bind/unbind/unbindAll', () {
    var element = new MyCustomElement();
    var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});

    element.bind('my-point', model, 'a');
    element.bind('scary-monster', model, 'b');

    expect(element.attributes, isNot(contains('my-point')));
    expect(element.attributes, isNot(contains('scary-monster')));

    expect(element.myPoint, model['a']);
    expect(element.scaryMonster, model['b']);

    model['a'] = null;
    performMicrotaskCheckpoint();
    expect(element.myPoint, null);
    element.unbind('my-point');

    model['a'] = new Point(1, 2);
    model['b'] = new Monster(200);
    performMicrotaskCheckpoint();
    expect(element.scaryMonster, model['b']);
    expect(element.myPoint, null, reason: 'a was unbound');

    element.unbindAll();
    model['b'] = null;
    performMicrotaskCheckpoint();
    expect(element.scaryMonster.health, 200);
  });

  observeTest('override attribute setter', () {
    var element = new WithAttrsCustomElement().real;
    var model = toObservable({'a': 1, 'b': 2});
    element.bind('hidden?', model, 'a');
    element.bind('id', model, 'b');

    expect(element.attributes, contains('hidden'));
    expect(element.attributes['hidden'], '');
    expect(element.id, '2');

    model['a'] = null;
    performMicrotaskCheckpoint();
    expect(element.attributes, isNot(contains('hidden')),
        reason: 'null is false-y');

    model['a'] = false;
    performMicrotaskCheckpoint();
    expect(element.attributes, isNot(contains('hidden')));

    model['a'] = 'foo';
    // TODO(jmesserly): this is here to force an ordering between the two
    // changes. Otherwise the order depends on what order StreamController
    // chooses to fire the two listeners in.
    performMicrotaskCheckpoint();

    model['b'] = 'x';
    performMicrotaskCheckpoint();
    expect(element.attributes, contains('hidden'));
    expect(element.attributes['hidden'], '');
    expect(element.id, 'x');

    expect(element.xtag.attributes.log, [
      ['remove', 'hidden?'],
      ['[]=', 'hidden', ''],
      ['[]=', 'id', '2'],
      ['remove', 'hidden'],
      ['remove', 'hidden'],
      ['[]=', 'hidden', ''],
      ['[]=', 'id', 'x'],
    ]);
  });

  observeTest('template bind uses overridden custom element bind', () {

    var model = toObservable({'a': new Point(123, 444), 'b': new Monster(100)});

    var div = createTestHtml('<template bind>'
          '<my-custom-element my-point="{{a}}" scary-monster="{{b}}">'
          '</my-custom-element>'
        '</template>');

    callback(fragment) {
      for (var e in fragment.queryAll('my-custom-element')) {
        new MyCustomElement.attach(e);
      }
    }
    mdv.instanceCreated.add(callback);

    div.query('template').model = model;
    performMicrotaskCheckpoint();

    var element = div.nodes[1];

    expect(element.xtag is MyCustomElement, true,
        reason: '${element.xtag} should be a MyCustomElement');

    expect(element.xtag.myPoint, model['a']);
    expect(element.xtag.scaryMonster, model['b']);

    expect(element.attributes, isNot(contains('my-point')));
    expect(element.attributes, isNot(contains('scary-monster')));

    model['a'] = null;
    performMicrotaskCheckpoint();
    expect(element.xtag.myPoint, null);

    div.query('template').model = null;
    performMicrotaskCheckpoint();

    expect(element.parentNode, null, reason: 'element was detached');

    model['a'] = new Point(1, 2);
    model['b'] = new Monster(200);
    performMicrotaskCheckpoint();

    expect(element.xtag.myPoint, null, reason: 'model was unbound');
    expect(element.xtag.scaryMonster.health, 100, reason: 'model was unbound');

    mdv.instanceCreated.remove(callback);
  });

}

class Monster {
  int health;
  Monster(this.health);
}

/** Demonstrates a custom element overriding bind/unbind/unbindAll. */
class MyCustomElement implements Element {
  final Element real;

  Point myPoint;
  Monster scaryMonster;

  MyCustomElement() : this.attach(new Element.tag('my-custom-element'));

  MyCustomElement.attach(this.real) {
    real.xtag = this;
  }

  get attributes => real.attributes;
  get bindings => real.bindings;

  NodeBinding createBinding(String name, model, String path) {
    switch (name) {
      case 'my-point':
      case 'scary-monster':
        return new _MyCustomBinding(this, name, model, path);
    }
    return real.createBinding(name, model, path);
  }

  bind(String name, model, String path) => real.bind(name, model, path);
  void unbind(String name) => real.unbind(name);
  void unbindAll() => real.unbindAll();
}

class _MyCustomBinding extends mdv.NodeBinding {
  _MyCustomBinding(MyCustomElement node, property, model, path)
      : super(node, property, model, path) {

    node.attributes.remove(property);
  }

  MyCustomElement get node => super.node;

  void boundValueChanged(newValue) {
    if (property == 'my-point') node.myPoint = newValue;
    if (property == 'scary-monster') node.scaryMonster = newValue;
  }
}


/**
 * Demonstrates a custom element can override attributes []= and remove.
 * and see changes that the data binding system is making to the attributes.
 */
class WithAttrsCustomElement implements Element {
  final Element real;
  final AttributeMapWrapper<String, String> attributes;

  factory WithAttrsCustomElement() {
    var real = new Element.tag('with-attrs-custom-element');
    var attributes = new AttributeMapWrapper(real.attributes);
    return new WithAttrsCustomElement._(real, attributes);
  }

  WithAttrsCustomElement._(this.real, this.attributes) {
    real.xtag = this;
  }

  createBinding(String name, model, String path) =>
      real.createBinding(name, model, path);
  bind(String name, model, String path) => real.bind(name, model, path);
  void unbind(String name) => real.unbind(name);
  void unbindAll() => real.unbindAll();
}

// TODO(jmesserly): would be nice to use mocks when mirrors work on dart2js.
class AttributeMapWrapper<K, V> implements Map<K, V> {
  final List log = [];
  Map<K, V> _map;

  AttributeMapWrapper(this._map);

  bool containsValue(Object value) => _map.containsValue(value);
  bool containsKey(Object key) => _map.containsKey(key);
  V operator [](Object key) => _map[key];

  void operator []=(K key, V value) {
    log.add(['[]=', key, value]);
    _map[key] = value;
  }

  V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent);

  V remove(Object key) {
    log.add(['remove', key]);
    _map.remove(key);
  }

  void clear() => _map.clear();
  void forEach(void f(K key, V value)) => _map.forEach(f);
  Iterable<K> get keys => _map.keys;
  Iterable<V> get values => _map.values;
  int get length => _map.length;
  bool get isEmpty => _map.isEmpty;
  bool get isNotEmpty => _map.isNotEmpty;
}

/**
 * Sanitizer which does nothing.
 */
class NullTreeSanitizer implements NodeTreeSanitizer {
  void sanitizeTree(Node node) {}
}
