
define([
    "./queue"
], function (queue) {
    
    queue.prototype.byId = function byId(id, handler, options) {
        var self = this;
        this.then(function byIdTask() {
            options = options || {};
            self._query("#" + id, self._wrapHandler(handler), options);
        });
    };
    
    queue.prototype.query = function query(selector, handler, options) {
        var self = this;
        this.then(function queryTask() {
            options = options || {};
            self._query(selector, self._wrapHandler(handler), options);
        });
    };
    
    queue.prototype.queryAll = function queryAll(selector, expectedCount, handler, options) {
        var self = this;
        this.then(function queryAllTask() {
            options = options || {};
            self._queryAll(selector, expectedCount, self._wrapHandler(handler), options);
        });
    };
    
    queue.prototype._query = function _query(selector, handler, options) {
        this._queryAll(selector, ">0", this._wrapWithUnpackArray(handler), options);
    };
    
    queue.prototype._queryAll = function _queryAll(selector, expected, handler, options) {
        this._waitFor(this._createQueryFunction(selector, expected, options), handler, options);
    };
    
    queue.prototype._createQueryFunction = function _createQueryFunction(selector, expected, options) {
        var expectedFunc;
        
        if (typeof expected === "string") {
            expectedFunc = this._stringElementCountComparitor(expected);
        } else if (typeof expected === "number") {
            expectedFunc = function (elements) {
                return elements.length === expected;
            };
        } else {
            expectedFunc = expected;
        }
        
        var self = this;
        return function queryFunction() {
            options = options || {};
            
            // 3 possible types of queries, default document, element, or custom document
            var elements;
            if (options.document) {
                elements = options.document.querySelectorAll(selector);
            } else if (options.scopeElement) {
                elements = options.scopeElement.querySelectorAll(selector);
            } else {
                elements = self.document.querySelectorAll(selector);
            }
            
            if (expectedFunc(elements)) {
                return elements;
            } else {
                var msg = "Found " + elements.length + " elements but expected " + expected +
                        " using selector: '" + selector + "'";
                if (options.document) {
                    msg += " on document: '" + options.document.location + "'";
                } else if (options.scopeElement) {
                    msg += " on element: '" + options.scopeElement + "'";
                }
                throw new Error(msg);
            }  
        };
    };
    
    queue.prototype._stringElementCountComparitor = function _stringElementCountComparitor(expected) {
        var i, token;
        // first we have to add spaces around all the symbols so that we can split on spaces
        var tempExpected = expected.replace(/([<>=&|])/g, " $1 ");
        // we can't just use split with the symbols because we'd lose them in the output (capture
        // isn't widely supported cross-browser)
        var rawTokens = tempExpected.split(" ");
        
        var tokens = [];
        for (i in rawTokens) {
            token = rawTokens[i].replace(/^\s+|\s+$/g, "");
            if (token.length > 0) {
                tokens.push(token);
            }
        }
        
        var errorMessage = "Illegal query count expectation string: '" + expected + "'";
        if (tokens.length < 2) {
            throw new Error(errorMessage);
        }
        
        return function _stringBasedElementCount(elements) {
            var valid = true;
            var comparison = "&";
            var num;
            for (i = 0; i < tokens.length; i += 3) {
                num = parseInt(tokens[i + 1], 10);
                if (!isNaN(num)) {
                    if (tokens[i] === "<") {
                        if (comparison === "&") {
                            valid &= elements.length < num;
                        } else {
                            valid |= elements.length < num;
                        }
                    } else if (tokens[i] === ">") {
                        if (comparison === "&") {
                            valid &= elements.length > num;
                        } else {
                            valid |= elements.length > num;
                        }
                    } else if (tokens[i] === "=") {
                        if (comparison === "&") {
                            valid &= elements.length === num;
                        } else {
                            valid |= elements.length === num;
                        }
                    } else {
                        throw new Error(errorMessage)
                    }
                } else {
                    throw new Error(errorMessage);
                }
                comparison = tokens[i + 2];
                if (comparison !== undefined && comparison !== "&" && comparison !== "|") {
                    throw new Error(errorMessage);
                }
            }
            return valid;
        };
    };
    
    queue.prototype._wrapWithUnpackArray = function _wrapWithUnpackArray(handler) {
        return function _unpackArrayHelper() {
            // unpack the first argument out of it's array'
            arguments[0] = arguments[0][0];
            handler.apply(this, arguments);
        };
    };
    
    queue.prototype._normalizeElement = function _normalizeElement(element, handler, options) {
        if (typeof element === "string") {
            this._query(element, handler, options);
        } else {
            handler.call(this, element);
        }
    };    
    
    queue.prototype._findParentByType = function _findParentByType(element, type) {
        while (element.parentNode && 
                element.parentNode.tagName &&
                element.parentNode.tagName.toLowerCase() !== type) {
                
            element = element.parentNode;
        }
        return element.parentNode;
    };
    
    return queue;
});

@@ -165,21 +165,13 @@
 ion 
-byIdTask
 () %7B%0A
+
     
@@ -428,17 +428,8 @@
 ion 
-queryTask
 () %7B
@@ -712,20 +712,8 @@
 ion 
-queryAllTask
 () %7B
@@ -939,32 +939,39 @@
 ions) %7B%0A        
+return 
 this._queryAll(s
@@ -1138,221 +1138,8 @@
 ) %7B%0A
-        this._waitFor(this._createQueryFunction(selector, expected, options), handler, options);%0A    %7D;%0A    %0A    queue.prototype._createQueryFunction = function _createQueryFunction(selector, expected, options) %7B%0A
     
@@ -1514,33 +1514,25 @@
 ;%0A        %7D%0A
-        
 %0A
+
         var 
@@ -1544,39 +1544,46 @@
 = this;%0A        
-return 
+this._waitFor(
 function queryFu
@@ -1580,20 +1580,24 @@
 on query
-Func
+AllCondi
 tion() %7B
@@ -2678,18 +2678,16 @@
        %7D
-  
 %0A       
@@ -2680,32 +2680,51 @@
      %7D%0A        %7D
+, handler, options)
 ;%0A    %7D;%0A    %0A  

Revert "Slight refactor of the dom query wait method."