import { fireEvent, matches } from '../system/synthetic-events';

export default class NodeQuery {
  static query(selector, context = document) {
    return new NodeQuery(context.querySelectorAll(selector));
  }

  static element(element) {
    return new NodeQuery([element]);
  }

  constructor(nodes) {
    this.nodes = nodes;

    for (let i=0; i<nodes.length; i++) {
      this[i] = nodes[i];
    }

    this.length = nodes.length;

    Object.freeze(this);
  }

  find(selector) {
    assertSingle(this);

    return this[0].querySelector(selector);
  }

  findAll(selector) {
    let nodes = [];

    for (let node of this.nodes) {
      nodes.push(...node.querySelectorAll(selector));
    }

    return new NodeQuery(nodes);
  }

  trigger(eventName, options) {
    let events = [];

    for (let node of this.nodes) {
      events.push(fireEvent(node, eventName, options));
    }

    return events;
  }

  click() {
    return this.trigger('click');
  }

  text() {
    let out = "";

    for (let node of this.nodes) {
      out += node.innerText;
    }

    return out;
  }

  attr(name) {
    if (arguments.length !== 1) {
      throw new Error('not implemented');
    }

    assertSingle(this);

    return this.nodes[0].getAttribute(name);
  }

  prop(name, value) {
    if (arguments.length > 1) {
      return this.setProp(name, value);
    }

    assertSingle(this);

    return this.nodes[0][name];
  }

  setProp(name, value) {
    for (let node of this.nodes) {
      node[name] = value;
    }

    return this;
  }

  val(value) {
    if (arguments.length === 1) {
      return this.setProp('value', value);
    }

    return this.prop('value');
  }

  is(selector) {
    for (let node of this.nodes) {
      if (!matches(node, selector)) {
        return false;
      }
    }

    return true;
  }

  hasClass(className) {
    return this.is(`.${className}`);
  }
}

function assertSingle(nodeQuery) {
  if (nodeQuery.length !== 1) {
    throw new Error(`attr(name) called on a NodeQuery with ${this.nodes.length} elements. Expected one element.`);
  }
}

@@ -1,8 +1,46 @@
+import %7B assert %7D from 'ember-debug';%0A
 import %7B
@@ -202,16 +202,24 @@
 deQuery(
+toArray(
 context.
@@ -241,24 +241,25 @@
 l(selector))
+)
 ;%0A  %7D%0A%0A  sta
@@ -342,24 +342,112 @@
 or(nodes) %7B%0A
+    assert(Array.isArray(nodes), 'NodeQuery must be initialized with a literal array');%0A
     this.nod
@@ -740,36 +740,34 @@
     
-for (let node of this.
+this.nodes.forEach(
 node
-s)
+ =%3E
  %7B%0A 
@@ -816,32 +816,34 @@
 elector));%0A    %7D
+);
 %0A%0A    return new
@@ -906,79 +906,38 @@
     
-let events = %5B%5D;%0A%0A    for (let node of this.nodes) %7B%0A      events.push(
+return this.nodes.map(node =%3E 
 fire
@@ -974,34 +974,8 @@
 ));%0A
-    %7D%0A%0A    return events;%0A
   %7D%0A
@@ -1045,108 +1045,62 @@
     
-let out = %22%22;%0A%0A    for (let node of this.nodes) %7B%0A      out += node.innerText;%0A    %7D%0A%0A    return out
+return this.nodes.map(node =%3E node.innerText).join('')
 ;%0A  
@@ -1471,44 +1471,34 @@
     
-for (let node of this.nodes) %7B%0A     
+this.nodes.forEach(node =%3E
  nod
@@ -1512,23 +1512,18 @@
  = value
+)
 ;
-%0A    %7D
 %0A%0A    re
@@ -1698,129 +1698,64 @@
     
-for (let node of this.nodes) %7B%0A      if (!matches(node, selector)) %7B%0A        return false;%0A      %7D%0A    %7D%0A%0A    return true
+return this.nodes.every(node =%3E matches(node, selector))
 ;%0A  
@@ -2005,16 +2005,144 @@
 ement.%60);%0A  %7D%0A%7D%0A
+%0Afunction toArray(nodes) %7B%0A  let out = %5B%5D;%0A%0A  for (let i=0; i%3Cnodes.length; i++) %7B%0A    out.push(nodes%5Bi%5D);%0A  %7D%0A%0A  return out;%0A%7D%0A

Clean up the code to not rely on newer features