/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */
part of charted.selection;

/**
 * Implementation of [Selection].
 * Selections cannot be created directly - they are only created using
 * the select or selectAll methods on [SelectionScope] and [Selection].
 */
class _SelectionImpl implements Selection {
  List<SelectionGroup> groups;
  SelectionScope scope;

  /**
   * Creates a new selection.
   *
   * When [source] is not specified, the new selection would have exactly
   * one group with [SelectionScope.root] as it's parent.  Otherwise, one group
   * per for each non-null element is created with element as it's parent.
   *
   * When [selector] is specified, each group contains all elements matching
   * [selector] and under the group's parent element.  Otherwise, [fn] is
   * called once per group with parent element's "data", "index" and the
   * "element" itself passed as parameters.  [fn] must return an iterable of
   * elements to be used in each group.
   */
  _SelectionImpl.all(
      {String selector,
      SelectionCallback<List<Element>> fn,
      SelectionScope this.scope,
      Selection source}) {
    assert(selector != null || fn != null);
    assert(source != null || scope != null);

    if (selector != null) {
      fn = (d, i, c) => c == null
          ? scope.root.querySelectorAll(selector)
          : c.querySelectorAll(selector);
    }

    var tmpGroups = new List<SelectionGroup>();
    if (source != null) {
      scope = source.scope;
      for (int gi = 0; gi < source.groups.length; ++gi) {
        final g = source.groups.elementAt(gi);
        for (int ei = 0; ei < g.elements.length; ++ei) {
          final e = g.elements.elementAt(ei);
          if (e != null) {
            tmpGroups.add(
                new _SelectionGroupImpl(fn(scope.datum(e), gi, e), parent: e));
          }
        }
      }
    } else {
      tmpGroups
          .add(new _SelectionGroupImpl(fn(null, 0, null), parent: scope.root));
    }
    groups = tmpGroups;
  }

  /**
   * Same as [all] but only uses the first element matching [selector] when
   * [selector] is specified.  Otherwise, call [fn] which must return the
   * element to be selected.
   */
  _SelectionImpl.single(
      {String selector,
      SelectionCallback<Element> fn,
      SelectionScope this.scope,
      Selection source}) {
    assert(selector != null || fn != null);
    assert(source != null || scope != null);

    if (selector != null) {
      fn = (d, i, c) => c == null
          ? scope.root.querySelector(selector)
          : c.querySelector(selector);
    }

    if (source != null) {
      scope = source.scope;
      groups = new List<SelectionGroup>.generate(source.groups.length, (gi) {
        SelectionGroup g = source.groups.elementAt(gi);
        return new _SelectionGroupImpl(
            new List.generate(g.elements.length, (ei) {
              var e = g.elements.elementAt(ei);
              if (e != null) {
                var datum = scope.datum(e);
                var enterElement = fn(datum, ei, e);
                if (datum != null) {
                  scope.associate(enterElement, datum);
                }
                return enterElement;
              } else {
                return null;
              }
            }),
            parent: g.parent);
      });
    } else {
      groups = new List<SelectionGroup>.generate(
          1,
          (_) => new _SelectionGroupImpl(
              new List.generate(1, (_) => fn(null, 0, null), growable: false)),
          growable: false);
    }
  }

  /** Creates a selection using the pre-computed list of [SelectionGroup] */
  _SelectionImpl.selectionGroups(this.groups, this.scope);

  /**
   * Creates a selection using the list of elements. All elements will
   * be part of the same group, with [SelectionScope.root] as the group's parent
   */
  _SelectionImpl.elements(
      Iterable<Element> elements, SelectionScope this.scope) {
    groups = new List<SelectionGroup>()
      ..add(new _SelectionGroupImpl(elements.toList()));
  }

  /**
   * Utility to evaluate value of parameters (uses value when given
   * or invokes a callback to get the value) and calls [action] for
   * each non-null element in this selection
   */
  void _do(SelectionCallback f, Function action) {
    each((d, i, e) => action(e, f == null ? null : f(scope.datum(e), i, e)));
  }

  /** Calls a function on each non-null element in the selection */
  void each(SelectionCallback fn) {
    if (fn == null) return;
    for (int gi = 0, gLen = groups.length; gi < gLen; ++gi) {
      final g = groups.elementAt(gi);
      for (int ei = 0, eLen = g.elements.length; ei < eLen; ++ei) {
        final e = g.elements.elementAt(ei);
        if (e != null) fn(scope.datum(e), ei, e);
      }
    }
  }

  void on(String type, [SelectionCallback listener, bool capture]) {
    EventListener getEventHandler(int i, Element e) => (Event event) {
          var previous = scope.event;
          scope.event = event;
          try {
            listener(scope.datum(e), i, e);
          } finally {
            scope.event = previous;
          }
        };

    if (!type.startsWith('.')) {
      if (listener != null) {
        // Add a listener to each element.
        each((d, i, Element e) {
          var handlers = scope._listeners[e];
          if (handlers == null) scope._listeners[e] = handlers = {};
          handlers[type] = new Pair(getEventHandler(i, e), capture);
          e.addEventListener(type, handlers[type].first, capture);
        });
      } else {
        // Remove the listener from each element.
        each((d, i, Element e) {
          var handlers = scope._listeners[e];
          if (handlers != null && handlers[type] != null) {
            e.removeEventListener(
                type, handlers[type].first, handlers[type].last);
          }
        });
      }
    } else {
      // Remove all listeners on the event type (ignoring the namespace)
      each((d, i, Element e) {
        var handlers = scope._listeners[e], t = type.substring(1);
        handlers.forEach((String s, Pair<EventListener, bool> value) {
          if (s.split('.')[0] == t) {
            e.removeEventListener(s, value.first, value.last);
          }
        });
      });
    }
  }

  int get length {
    int retval = 0;
    each((d, i, e) => retval++);
    return retval;
  }

  bool get isEmpty => length == 0;

  /** First non-null element in this selection */
  Element get first {
    for (int gi = 0; gi < groups.length; gi++) {
      SelectionGroup g = groups.elementAt(gi);
      for (int ei = 0; ei < g.elements.length; ei++) {
        if (g.elements.elementAt(ei) != null) {
          return g.elements.elementAt(ei);
        }
      }
    }
    return null;
  }

  void attr(String name, val) {
    assert(name != null && name.isNotEmpty);
    attrWithCallback(name, toCallback(val));
  }

  void attrWithCallback(String name, SelectionCallback fn) {
    assert(fn != null);
    _do(
        fn,
        (e, v) =>
            v == null ? e.attributes.remove(name) : e.attributes[name] = "$v");
  }

  void classed(String name, [bool val = true]) {
    assert(name != null && name.isNotEmpty);
    classedWithCallback(name, toCallback(val));
  }

  void classedWithCallback(String name, SelectionCallback<bool> fn) {
    assert(fn != null);
    _do(fn,
        (e, v) => v == false ? e.classes.remove(name) : e.classes.add(name));
  }

  void style(String property, val, {String priority}) {
    assert(property != null && property.isNotEmpty);
    styleWithCallback(property, toCallback(val as String), priority: priority);
  }

  void styleWithCallback(String property, SelectionCallback<String> fn,
      {String priority}) {
    assert(fn != null);
    _do(
        fn,
        (Element e, String v) => v == null || v.isEmpty
            ? e.style.removeProperty(property)
            : e.style.setProperty(property, v, priority));
  }

  void text(String val) => textWithCallback(toCallback(val));

  void textWithCallback(SelectionCallback<String> fn) {
    assert(fn != null);
    _do(fn, (e, v) => e.text = v == null ? '' : v);
  }

  void html(String val) => htmlWithCallback(toCallback(val));

  void htmlWithCallback(SelectionCallback<String> fn) {
    assert(fn != null);
    _do(fn, (e, v) => e.innerHtml = v == null ? '' : v);
  }

  void remove() => _do(null, (e, _) => e.remove());

  Selection select(String selector) {
    assert(selector != null && selector.isNotEmpty);
    return new _SelectionImpl.single(selector: selector, source: this);
  }

  Selection selectWithCallback(SelectionCallback<Element> fn) {
    assert(fn != null);
    return new _SelectionImpl.single(fn: fn, source: this);
  }

  Selection append(String tag) {
    assert(tag != null && tag.isNotEmpty);
    return appendWithCallback(
        (d, ei, e) => Namespace.createChildElement(tag, e));
  }

  Selection appendWithCallback(SelectionCallback<Element> fn) {
    assert(fn != null);
    return new _SelectionImpl.single(
        fn: (datum, ei, e) {
          Element child = fn(datum, ei, e);
          return child == null ? null : e.append(child) as Element;
        },
        source: this);
  }

  Selection insert(String tag,
      {String before, SelectionCallback<Element> beforeFn}) {
    assert(tag != null && tag.isNotEmpty);
    return insertWithCallback(
        (d, ei, e) => Namespace.createChildElement(tag, e),
        before: before,
        beforeFn: beforeFn);
  }

  Selection insertWithCallback(SelectionCallback<Element> fn,
      {String before, SelectionCallback<Element> beforeFn}) {
    assert(fn != null);
    beforeFn =
        before == null ? beforeFn : (d, ei, e) => e.querySelector(before);
    return new _SelectionImpl.single(
        fn: (datum, ei, e) {
          Element child = fn(datum, ei, e);
          Element before = beforeFn(datum, ei, e);
          return child == null
              ? null
              : e.insertBefore(child, before) as Element;
        },
        source: this);
  }

  Selection selectAll(String selector) {
    assert(selector != null && selector.isNotEmpty);
    return new _SelectionImpl.all(selector: selector, source: this);
  }

  Selection selectAllWithCallback(SelectionCallback<List<Element>> fn) {
    assert(fn != null);
    return new _SelectionImpl.all(fn: fn, source: this);
  }

  DataSelection data(Iterable vals, [SelectionKeyFunction keyFn]) {
    assert(vals != null);
    return dataWithCallback(toCallback(vals), keyFn);
  }

  DataSelection dataWithCallback(SelectionCallback<Iterable> fn,
      [SelectionKeyFunction keyFn]) {
    assert(fn != null);

    var enterGroups = <SelectionGroup>[],
        updateGroups = <SelectionGroup>[],
        exitGroups = <SelectionGroup>[];

    // Create a dummy node to be used with enter() selection.
    Element dummy(val) {
      var element = new Element.div();
      scope.associate(element, val);
      return element;
    }

    ;

    // Joins data to all elements in the group.
    void join(SelectionGroup g, Iterable vals) {
      final int valuesLength = vals.length;
      final int elementsLength = g.elements.length;

      // Nodes exiting, entering and updating in this group.
      // We maintain the nodes at the same index as they currently
      // are (for exiting) or where they should be (for entering and updating)
      var update = new List<Element>(valuesLength);
      var enter = new List<Element>(valuesLength);
      var exit = new List<Element>(elementsLength);

      // Use key function to determine DOMElement to data associations.
      if (keyFn != null) {
        var keysOnDOM = [], elementsByKey = {}, valuesByKey = {};

        // Create a key to DOM element map.
        // Used later to see if an element already exists for a key.
        for (int ei = 0, len = elementsLength; ei < len; ++ei) {
          final e = g.elements.elementAt(ei);
          var keyValue = keyFn(scope.datum(e));
          if (elementsByKey.containsKey(keyValue)) {
            exit[ei] = e;
          } else {
            elementsByKey[keyValue] = e;
          }
          keysOnDOM.add(keyValue);
        }

        // Iterate through the values and find values that don't have
        // corresponding elements in the DOM, collect the entering elements.
        for (int vi = 0, len = valuesLength; vi < len; ++vi) {
          final v = vals.elementAt(vi);
          var keyValue = keyFn(v);
          Element e = elementsByKey[keyValue];
          if (e != null) {
            update[vi] = e;
            scope.associate(e, v);
          } else if (!valuesByKey.containsKey(keyValue)) {
            enter[vi] = dummy(v);
          }
          valuesByKey[keyValue] = v;
          elementsByKey.remove(keyValue);
        }

        // Iterate through the previously saved keys to
        // find a list of elements that don't have data anymore.
        // We don't use elementsByKey.keys() because that does not
        // guarantee the order of returned keys.
        for (int i = 0, len = elementsLength; i < len; ++i) {
          if (elementsByKey.containsKey(keysOnDOM[i])) {
            exit[i] = g.elements.elementAt(i);
          }
        }
      } else {
        // When we don't have the key function, just use list index as the key
        int updateElementsCount = math.min(elementsLength, valuesLength);
        int i = 0;

        // Collect a list of elements getting updated in this group
        for (int len = updateElementsCount; i < len; ++i) {
          var e = g.elements.elementAt(i);
          if (e != null) {
            scope.associate(e, vals.elementAt(i));
            update[i] = e;
          } else {
            enter[i] = dummy(vals.elementAt(i));
          }
        }

        // List of elements newly getting added
        for (int len = valuesLength; i < len; ++i) {
          enter[i] = dummy(vals.elementAt(i));
        }

        // List of elements exiting this group
        for (int len = elementsLength; i < len; ++i) {
          exit[i] = g.elements.elementAt(i);
        }
      }

      // Create the element groups and set parents from the current group.
      enterGroups.add(new _SelectionGroupImpl(enter, parent: g.parent));
      updateGroups.add(new _SelectionGroupImpl(update, parent: g.parent));
      exitGroups.add(new _SelectionGroupImpl(exit, parent: g.parent));
    }

    ;

    for (int gi = 0; gi < groups.length; ++gi) {
      final g = groups.elementAt(gi);
      join(g, fn(scope.datum(g.parent), gi, g.parent));
    }

    return new _DataSelectionImpl(updateGroups, enterGroups, exitGroups, scope);
  }

  void datum(Iterable vals) {
    throw new UnimplementedError();
  }

  void datumWithCallback(SelectionCallback<Iterable> fn) {
    throw new UnimplementedError();
  }

  Transition transition() => new Transition(this);
}

/* Implementation of [DataSelection] */
class _DataSelectionImpl extends _SelectionImpl implements DataSelection {
  EnterSelection enter;
  ExitSelection exit;

  _DataSelectionImpl(
      List<SelectionGroup> updated,
      List<SelectionGroup> entering,
      List<SelectionGroup> exiting,
      SelectionScope scope)
      : super.selectionGroups(updated, scope) {
    enter = new _EnterSelectionImpl(entering, this);
    exit = new _ExitSelectionImpl(exiting, this);
  }
}

/* Implementation of [EnterSelection] */
class _EnterSelectionImpl implements EnterSelection {
  final DataSelection update;

  SelectionScope scope;
  Iterable<SelectionGroup> groups;

  _EnterSelectionImpl(this.groups, this.update) {
    scope = update.scope;
  }

  bool get isEmpty => false;

  Selection insert(String tag,
      {String before, SelectionCallback<Element> beforeFn}) {
    assert(tag != null && tag.isNotEmpty);
    return insertWithCallback(
        (d, ei, e) => Namespace.createChildElement(tag, e),
        before: before,
        beforeFn: beforeFn);
  }

  Selection insertWithCallback(SelectionCallback<Element> fn,
      {String before, SelectionCallback<Element> beforeFn}) {
    assert(fn != null);
    return selectWithCallback((d, ei, e) {
      Element child = fn(d, ei, e);
      e.insertBefore(child, e.querySelector(before));
      return child;
    });
  }

  Selection append(String tag) {
    assert(tag != null && tag.isNotEmpty);
    return appendWithCallback(
        (d, ei, e) => Namespace.createChildElement(tag, e));
  }

  Selection appendWithCallback(SelectionCallback<Element> fn) {
    assert(fn != null);
    return selectWithCallback((datum, ei, e) {
      Element child = fn(datum, ei, e);
      e.append(child);
      return child;
    });
  }

  Selection select(String selector) {
    assert(selector == null && selector.isNotEmpty);
    return selectWithCallback((d, ei, e) => e.querySelector(selector));
  }

  Selection selectWithCallback(SelectionCallback<Element> fn) {
    var subgroups = <SelectionGroup>[];
    for (int gi = 0, len = groups.length; gi < len; ++gi) {
      final g = groups.elementAt(gi);
      final u = update.groups.elementAt(gi);
      final subgroup = <Element>[];
      for (int ei = 0, eLen = g.elements.length; ei < eLen; ++ei) {
        final e = g.elements.elementAt(ei);
        if (e != null) {
          var datum = scope.datum(e), selected = fn(datum, ei, g.parent);
          scope.associate(selected, datum);
          u.elements[ei] = selected;
          subgroup.add(selected);
        } else {
          subgroup.add(null);
        }
      }
      subgroups.add(new _SelectionGroupImpl(subgroup, parent: g.parent));
    }
    return new _SelectionImpl.selectionGroups(subgroups, scope);
  }
}

/* Implementation of [ExitSelection] */
class _ExitSelectionImpl extends _SelectionImpl implements ExitSelection {
  final DataSelection update;
  _ExitSelectionImpl(List<SelectionGroup> groups, DataSelection update)
      : update = update,
        super.selectionGroups(groups, update.scope);
}

class _SelectionGroupImpl implements SelectionGroup {
  List<Element> elements;
  Element parent;
  _SelectionGroupImpl(this.elements, {this.parent});
}
