var pick = require('../pick');
var expect = require('chai').expect;

var john, katie, susan, hugh, lisa;

hugh = {
    "name" : "Hugh",
    "age"  : 58
};

lisa = {
    "name" : "Lisa",
    "age"  : 60
};

susan = {
    "name" : "Susan",
    "age" : 28,
    "parents" : {
        "mother" : lisa,
        "father" : hugh
    }
};

katie = {
    "name" : "Katie",
    "age" : 32
};

john = {
    "name" : "John",
    "age"  : 32,
    "relationships" : [
        { "status" : "ongoing", "with" : susan },
        { "status" : "ended", "with" : katie }
    ]
};

var persons = [john, susan, katie, hugh, lisa];

function testPick(path, matcher) {
    return function(data) {
        return function(expected) {
            var actual = pick(path, matcher)(data);
            expect(actual).to.eql(expected);
        };
    };
};

testSuite("basic path selection", {
    "select self":
        [testPick("/")(susan), susan],

    "select field from self":
        [testPick("/name")(susan), "Susan"],

    "select field from depth of one":
        [testPick("/parents/father")(susan), hugh],

    "select field from depth of two":
        [testPick("/parents/father/name")(susan), "Hugh"],

    "handle incomplete paths":
        [testPick("/parents/mother/spouse")(susan), undefined],

    "handle missing paths in middle":
        [testPick("/bestFriend/name")(susan), undefined]
});

testSuite("array selection", {
    "select self":
        [testPick("/")(persons), persons],

    "select all elements from self":
        [testPick("/[]")(persons), persons],

    "select index from self":
        [testPick("/[0]")(persons), john],

    "select index from self and subpath from that index":
        [testPick("/[0]/name")(persons), "John"],

    "handle missing indexes":
        [testPick("/[10]")(persons), undefined],

    "handle missing subpaths after indexed selection":
        [testPick("/[0]/bestFriend/name")(persons), undefined],

    "select first index for which the full path can be resolved using [*]":
        [testPick("/[*]/parents/father")(persons), hugh],

    "map self elements to the remaining path":
        [testPick("/[]/name")(persons), persons.map(pick("/name"))],

    "omit indexes that don't match subpath when using []":
        [testPick("/[]/parents/father"), persons, [hugh]]
});

function forEachKeyValue(object, fn) {
    var key;

    for (key in object) {
        if (object.hasOwnProperty(key)) {
            fn(key, object[key]);
        }
    }
}

function testSuite(description, tests) {
    describe(description, function() {
        forEachKeyValue(tests, function(testDescription, data) {
            var test = data[0];
            var expected = data[1];

            it("can " + testDescription, function() {
                test(expected);
            });
        });
    });
}


@@ -2310,16 +2310,605 @@
 %5D%5D%0A%7D);%0A%0A
+var numbers = %5B1,2,3,4,5,6,7,8,9,10%5D;%0Afunction isOdd(value)     %7B return value %25 2 !== 0; %7D %0Afunction greaterThan(min) %7B return function(value) %7B return value %3E min; %7D %7D%0A%0AtestSuite(%22user-provided matcher function%22, %7B%0A    %22selects value when it returns true%22:%0A        %5BtestPick(%22/%22, isOdd)(1), 1%5D,%0A%0A    %22discards value when it returns false%22:%0A        %5BtestPick(%22/%22, isOdd)(2), undefined%5D,%0A%0A    %22can be used to find first matching item%22:%0A        %5BtestPick(%22/%5B*%5D%22, greaterThan(5))(numbers), 6%5D,%0A%0A    %22can be used to filter arrays%22:%0A        %5BtestPick(%22/%5B%5D%22, isOdd)(numbers), %5B1,3,5,7,9%5D%5D%0A%7D);%0A%0A
 function

Add tests for user provided matcher functions