// 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.

part of mdv;

abstract class _InputBinding extends NodeBinding {
  StreamSubscription _eventSub;

  _InputBinding(node, name, model, path): super(node, name, model, path) {
    _eventSub = _getStreamForInputType(node).listen(nodeValueChanged);
  }

  void boundValueChanged(newValue);

  void nodeValueChanged(e);

  void close() {
    if (closed) return;
    _eventSub.cancel();
    super.close();
  }

  static EventStreamProvider<Event> _checkboxEventType = () {
    // Attempt to feature-detect which event (change or click) is fired first
    // for checkboxes.
    var div = new DivElement();
    var checkbox = div.append(new InputElement());
    checkbox.type = 'checkbox';
    var fired = [];
    checkbox.onClick.listen((e) {
      fired.add(Element.clickEvent);
    });
    checkbox.onChange.listen((e) {
      fired.add(Element.changeEvent);
    });
    checkbox.dispatchEvent(new MouseEvent('click', view: window));
    // WebKit/Blink don't fire the change event if the element is outside the
    // document, so assume 'change' for that case.
    return fired.length == 1 ? Element.changeEvent : fired.first;
  }();

  static Stream<Event> _getStreamForInputType(element) {
    switch (element.type) {
      case 'checkbox':
        return _checkboxEventType.forTarget(element);
      case 'radio':
      case 'select-multiple':
      case 'select-one':
        return element.onChange;
      default:
        return element.onInput;
    }
  }
}

class _ValueBinding extends _InputBinding {
  _ValueBinding(node, model, path) : super(node, 'value', model, path);

  get node => super.node;

  void boundValueChanged(newValue) {
    // Note: node can be an InputElement or TextAreaElement. Both have "value".
    (node as dynamic).value = sanitizeBoundValue(newValue);
  }

  void nodeValueChanged(e) {
    value = (node as dynamic).value;
  }
}

class _CheckedBinding extends _InputBinding {
  _CheckedBinding(node, model, path) : super(node, 'checked', model, path);

  InputElement get node => super.node;

  void boundValueChanged(newValue) {
    node.checked = _toBoolean(newValue);
  }

  void nodeValueChanged(e) {
    value = node.checked;

    // Only the radio button that is getting checked gets an event. We
    // therefore find all the associated radio buttons and update their
    // CheckedBinding manually.
    if (node is InputElement && node.type == 'radio') {
      for (var r in _getAssociatedRadioButtons(node)) {
        var checkedBinding = r.bindings['checked'];
        if (checkedBinding != null) {
          // Set the value directly to avoid an infinite call stack.
          checkedBinding.value = false;
        }
      }
    }
  }

  // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
  // Returns an array containing all radio buttons other than |element| that
  // have the same |name|, either in the form that |element| belongs to or,
  // if no form, in the document tree to which |element| belongs.
  //
  // This implementation is based upon the HTML spec definition of a
  // "radio button group":
  //   http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
  //
  static Iterable _getAssociatedRadioButtons(element) {
    if (!_isNodeInDocument(element)) return [];
    if (element.form != null) {
      return element.form.nodes.where((el) {
        return el != element &&
            el is InputElement &&
            el.type == 'radio' &&
            el.name == element.name;
      });
    } else {
      var radios = element.document.queryAll(
          'input[type="radio"][name="${element.name}"]');
      return radios.where((el) => el != element && el.form == null);
    }
  }

  // TODO(jmesserly): polyfill document.contains API instead of doing it here
  static bool _isNodeInDocument(Node node) {
    // On non-IE this works:
    // return node.document.contains(node);
    var document = node.document;
    if (node == document || node.parentNode == document) return true;
    return document.documentElement.contains(node);
  }
}

class _SelectedIndexBinding extends _InputBinding {
  _SelectedIndexBinding(node, model, path)
      : super(node, 'selectedIndex', model, path);

  SelectElement get node => super.node;

  void boundValueChanged(value) {
    var newValue = _toInt(value);
    if (newValue <= node.length) {
      node.selectedIndex = newValue;
      return;
    }

    // The binding may wish to bind to an <option> which has not yet been
    // produced by a child <template>. Furthermore, we may need to wait for
    // <optgroup> iterating and then for <option>.
    //
    // Unlike the JavaScript MDV, we don't have a special "Object.observe" event
    // loop to schedule on. (See the the "ensureScheduled" function:
    // https://github.com/Polymer/mdv/commit/9a51ad7ed74a292bf71662cea28acbd151ff65c8)
    //
    // Instead we use scheduleMicrotask. Each <template repeat> needs a delay of
    // 2:
    //   * once to happen after the child _TemplateIterator is created
    //   * once to be after _TemplateIterator.inputs CompoundBinding resolve
    // And then we need to do this delay sequence twice:
    //   * once for OPTGROUP
    //   * once for OPTION.
    // The resulting 2 * 2 is our maxRetries.
    var maxRetries = 4;
    delaySetSelectedIndex() {
      if (newValue > node.length && --maxRetries >= 0) {
        scheduleMicrotask(delaySetSelectedIndex);
      } else {
        node.selectedIndex = newValue;
      }
    }

    scheduleMicrotask(delaySetSelectedIndex);
  }

  void nodeValueChanged(e) {
    value = node.selectedIndex;
  }

  // TODO(jmesserly,sigmund): I wonder how many bindings typically convert from
  // one type to another (e.g. value-as-number) and whether it is useful to
  // have something like a int/num binding converter (either as a base class or
  // a wrapper).
  static int _toInt(value) {
    if (value is String) return int.parse(value, onError: (_) => null);
    return value is int ? value : null;
  }
}
