﻿var Query = function(array) {
    if (array.isPrototypeOf(Array))
        throw new Error("$.bind: Data skal være en array af objekter.");
    var _array = array;

    return {
        each: function(handler) {
            /// <SUMMARY>Iterator funktion, der kalder handleren for hvert element i arrayen: handler(item, idx)</SUMMARY>
            for (var i = 0; i < _array.length; i++)
                handler(_array[i], i);
            return new Query(_array);
        },

        where: function(predicate) {
            var predicateFunction;

            if (typeof predicate == "string") {
                predicateFunction = function(itm) {
                    with (itm) {
                        return eval(predicate);
                    }
                };
            }
            else {
                predicateFunction = predicate;
            }

            var result = [];
            new Query(_array).each(function(itm, i) {
                if (predicateFunction(itm))
                    result.push(itm);
            });
            return new Query(result);
        },

        limit: function(start, size) {
            return new Query(_array.slice(start, start + size));
        },
        select: function(clause) {
            var result = [];
            if (typeof clause == "string") {
                for (var i = 0; i < _array.length; i++)
                    result.push(eval(clause));
            }
            else {
                for (var i = 0; i < _array.length; i++)
                    result.push(clause(_array[i]));
            }
            return new Query(result);
        },

        orderBy: function(expression, direction) {
            ///<SUMMARY>Sorterer elementerne i henhold til expression udtrykket
            /// Hvis expression er en streng, forudsættes det at den er en property på alle elementer i array'et
            /// Hvis expression er en funktion, får den to array-elementer ind, og og forventes at returnerer -1, 0, 1.</SUMMARY>
            if (typeof direction != "string" || !/^(desc|asc)$/i.test(direction))
                throw new Error("Array.orderBy: direction argument, kan kun have værdien ASC eller DESC");
            var sortFunction;
            if (typeof expression == "string") {
                sortFunction = function(a, b) {
                    var i = a[expression] - b[expression];
                    if (isNaN(i)) {
                        i = a[expression].compare(b[expression]);
                    }
                    return i;
                }
            }
            else {
                sortFunction = expression;
            }
            var result = _array.clone();
            result.sort(sortFunction);
            if ((/desc/i).test(direction))
                result.reverse();
            return new Query(result);
        },

        clone: function() {
            var clone = [];
            new Querry(_array).each(function(itm) { clone.push(itm); });
            return new Query(clone);
        },

        render: function(template, renderCallback) {
            /// <SUMMARY>Udskriver alle elementer i følge skabelonen</SUMMARY>
            /// <PARAM name="template" type="string" />Streng med bindingssyntaks: Klammer med propertynavne. F.eks. Navn: {name}</PARAM>
            ///<PARAM name="renderCallback" />funktion der modtager resultatet af renderingen. funk(rowString, rowIdx)</PARAM>
            var result = [];
            var handler = (typeof renderCallback == "undefined") ?
        function(item) { result.push(template.bind(item)); } :
        function(item, idx) {
            var str = template.bind(item);
            result.push(str);
            renderCallback(str, idx);
        };
            new Querry(_array).each(handler);
            return new Query(result);
        },
        toArray: function() {
            return _array;
        }
    };
};


