<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<style>
* {
    color: black;
}
root.style1 target {
    color: rgb(1, 1, 1);
}

root.style2 > inert target {
    color: rgb(2, 2, 2);
}

root.style3 inert + target {
    color: rgb(3, 3, 3);
}

root.style4 > target inert {
    color: rgb(4, 4, 4);
}

root:not(.style5) target {
    color: rgb(5, 5, 5);
}

root.dynamicStyle notTarget {
    color: rgb(99, 99, 99);
}

</style>
</head>
<body>
    <root>
        <!-- With renderer -->
        <inert>
            <inert>
                <inert></inert>
                <target>
                    <inert></inert>
                    <target></target>
                </target>
            </inert>
            <target></target>
            <inert></inert>
        </inert>
    </root>
    <root style="display:none;">
        <!-- Without renderer -->
        <inert>
            <inert>
                <inert></inert>
                <target>
                    <inert></inert>
                    <target></target>
                </target>
            </inert>
            <target></target>
            <inert></inert>
        </inert>
    </root>
</body>
<script>

description('Test that we invalidate the element subtree minimally on class attribute change');

function testStyleChangeType(tag, type)
{
    var elements = document.querySelectorAll(tag);
    for (var i = 0; i < elements.length; ++i) {
        if (window.internals.styleChangeType(elements[i]) != type)
            return false;
    }
    return true;
}

function testStyleInvalidation(expectedDescendantStyleChange) {
    // Ideally we would't invalidate the root at all.
    shouldBeTrue('testStyleChangeType("root", "NoStyleChange") || testStyleChangeType("root", "InlineStyleChange")');

    shouldBeTrue('testStyleChangeType("target", "' + expectedDescendantStyleChange +'")');

    shouldBeTrue('testStyleChangeType("inert", "NoStyleChange")');
}

function addClass(name) {
    debug("Adding class " + name);
    var allRoots = document.querySelectorAll("root");
    allRoots[0].classList.add(name);
    allRoots[1].classList.add(name);
}

function removeClass(name) {
    debug("Removing class " + name);
    var allRoots = document.querySelectorAll("root");
    allRoots[0].classList.remove(name);
    allRoots[1].classList.remove(name);
}

function checkStyle(n) {
    document.documentElement.offsetTop;

    hasExpectedStyle = true;
    expectedColor = 'rgb('+n+', '+n+', '+n+')';
    var targets = document.querySelectorAll("target");
    for (var i = 0; i < targets.length; ++i) {
        hasExpectedStyle = getComputedStyle(targets[i]).color == expectedColor;
        if (!hasExpectedStyle)
            break;
    }
    shouldBeTrue("hasExpectedStyle");
}

addClass('style5');

checkStyle(0);
testStyleInvalidation("NoStyleChange");
checkStyle(0);

addClass('NotThere');
testStyleInvalidation("NoStyleChange");

addClass('style1');
testStyleInvalidation("InlineStyleChange");
checkStyle(1);

addClass('style2');
testStyleInvalidation("InlineStyleChange");
checkStyle(2);

removeClass('style2');
testStyleInvalidation("InlineStyleChange");
checkStyle(1);

addClass('style3');
testStyleInvalidation("InlineStyleChange");
checkStyle(3);

removeClass('style3');
testStyleInvalidation("InlineStyleChange");
checkStyle(1);

addClass('style4');
testStyleInvalidation("NoStyleChange");
checkStyle(1);

removeClass('NotThere');
testStyleInvalidation("NoStyleChange");

removeClass('style1');
testStyleInvalidation("InlineStyleChange");
checkStyle(0);

removeClass('style5');
testStyleInvalidation("InlineStyleChange");
checkStyle(5);

addClass('style5');
testStyleInvalidation("InlineStyleChange");
checkStyle(0);

addClass('dynamicStyle');
testStyleInvalidation("NoStyleChange");
checkStyle(0);

removeClass('dynamicStyle');
testStyleInvalidation("NoStyleChange");
checkStyle(0);

var dynamicSheet = document.createElement("style");
dynamicSheet.innerHTML = "root.dynamicStyle target { color:rgb(6, 6, 6); }"
debug("Inserting stylesheet '" + dynamicSheet.innerHTML + "'");
document.head.appendChild(dynamicSheet);

testStyleInvalidation("NoStyleChange");
checkStyle(0);

addClass('dynamicStyle');
testStyleInvalidation("InlineStyleChange");
checkStyle(6);

removeClass('dynamicStyle');
testStyleInvalidation("InlineStyleChange");
checkStyle(0)

</script>
<script src="../../resources/js-test-post.js"></script>
</html>
