var helper = require("./helper.js"),
    doc = helper.getFile("W3C_Selectors.html"),
    CSSselect = helper.CSSselect,
    soupselect = require("cheerio-soupselect"),
    selectors = [
        "body",
        "div",
        "body div",
        "div p",
        "div > p",
        "div + p",
        "div ~ p",
        "div[class^=exa][class$=mple]",
        "div p a",
        "div, p, a",
        ".note",
        "div.example",
        "ul .tocline2",
        "div.example, div.note",
        "#title",
        "h1#title",
        "div #title",
        "ul.toc li.tocline2",
        "ul.toc > li.tocline2",
        "h1#title + div > p",
        "h1[id]:contains(Selectors)",
        "a[href][lang][class]",
        "div[class]",
        "div[class=example]",
        "div[class^=exa]",
        "div[class$=mple]",
        "div[class*=e]",
        "div[class|=dialog]",
        "div[class!=made_up]",
        "div[class~=example]" /*, "div:not(.example)", "p:contains(selectors)", "p:nth-child(even)", "p:nth-child(2n)", "p:nth-child(odd)", "p:nth-child(2n+1)", "p:nth-child(n)", "p:only-child", "p:last-child", "p:first-child"*/
    ];

var engines = [
    function(a, b) {
        return CSSselect(b, a);
    },
    soupselect.select
];

//returns true when an error occurs
function testResult(rule) {
    var results = engines.map(function(func) {
        return func(doc, rule);
    });

    //check if both had the same result
    for (var i = 1; i < results.length; i++) {
        //TODO: might be hard to debug with more engines
        if (results[i - 1].length !== results[i].length) {
            //console.log(rule, results[i-1].length, results[i].length);
            return true;
        }
        for (var j = 0; j < results[i].length; j++) {
            if (results[i - 1][j] !== results[i][j]) {
                if (results[i - 1].indexOf(results[i][j]) === -1) {
                    return true;
                }
            }
        }
        //require("assert").deepEqual(results[i-1], results[i], rule + ": not the same elements");
    }

    return false;
}

selectors.filter(testResult).forEach(function(rule) {
    print(rule, "failed!\n");
});

process.exit(0); //don't run speed tests

print("-----\n\nChecking performance\n\n");

//test the speed
var ben = require("ben");

function testSpeed(rule) {
    print(rule, Array(28 - rule.length).join(" "));

    var results = engines.map(function(func) {
        return function() {
            return func(doc, rule);
        };
    });

    //also add a precompiled CSSselect test
    var compiled = CSSselect(rule);
    results.unshift(function() {
        return CSSselect.iterate(compiled, doc);
    });

    results = results.map(ben);

    var min = Math.min.apply(null, results);
    var max = Math.max.apply(null, results);

    results.forEach(function(result) {
        if (result === min) return print(" +", result, "+");
        if (result === max) return print(" !", result, "!");
        if (Math.abs(result - min) > Math.abs(result - max)) {
            return print(" =", result, "=");
        }
        print(" ~", result, "~");
    });

    print("\n");
}

print("RULE                    ", "CSSselect (pc)", "CSSselect", "soupselect\n");

selectors.forEach(testSpeed);

function print() {
    process.stdout.write(Array.prototype.join.call(arguments, " "));
}
