<html>
<head>
<script src="../../http/tests/inspector/inspector-test.js"></script>
<script src="../../http/tests/inspector/extensions-test.js"></script>
<script type="text/javascript">
function logMessage()
{
    console.log("hello");
}

function initialize_extensionsPanelTest()
{
    InspectorTest.getPanelSize = function()
    {
        var boundingRect = document.getElementById("main-panels").getBoundingClientRect();
        return {
            width: boundingRect.width,
            height: boundingRect.height
        };
    }

    InspectorTest.dumpStatusBarButtons = function()
    {
        var panel = WebInspector.inspectorView.currentPanel();
        var items = panel.statusBarItems();
        InspectorTest.addResult("Status bar buttons state:");
        for (var i = 0; i < items.length; ++i) {
            var item = items[i];
            if (!(item instanceof HTMLButtonElement)) {
                InspectorTest.addResult("status bar item " + i + " is not a button.");
                continue;
            }
            // Strip url(...) and prefix of the URL within, leave just last 3 components.
            var url = item.style.backgroundImage.replace(/^url\(.*(([/][^/]*){3}[^/)]*)\)$/, "...$1");
            InspectorTest.addResult("status bar item " + i + ", icon: " + url + ", tooltip: '" + item.title + "', disabled: " + item.disabled);
        }
    }

    InspectorTest.clickButton = function(index)
    {
        var panel = WebInspector.inspectorView.currentPanel();
        panel.statusBarItems()[index].click();
    }

    InspectorTest.clickOnURL = function()
    {
        WebInspector.showPanel("console");
        var xpathResult = document.evaluate("//a[starts-with(., 'extensions-panel.html')]",
                                            WebInspector.panel("console").element, null, XPathResult.ANY_UNORDERED_NODE_TYPE, null);
        var click = document.createEvent("MouseEvent");
        click.initMouseEvent("click", true, true);
        xpathResult.singleNodeValue.dispatchEvent(click);
    }
}

function extension_testCreatePanel(nextTest)
{
    var expectOnShown = false;

    function onPanelShown(panel, window)
    {
        if (!expectOnShown) {
            output("FAIL: unexpected onShown event");
            nextTest();
            return;
        }
        output("Panel shown");
        output("focused: " + window.document.hasFocus());
        panel.onShown.removeListener(onPanelShown);
        evaluateOnFrontend("reply(InspectorTest.getPanelSize())", function(result) {
            if (result.width !== window.innerWidth)
                output("panel width mismatch, outer: " + result.width + ", inner:" + window.innerWidth);
            else if (result.height !== window.innerHeight)
                output("panel height mismatch, outer: " + result.height + ", inner:" + window.innerHeight);
            else
                output("Extension panel size correct");
            nextTest();
        });
    }

    function onPanelCreated(panel)
    {
        output("Panel created");
        dumpObject(panel);
        panel.onHidden.addListener(function() {
            output("Panel hidden");
        });
        panel.onShown.addListener(onPanelShown.bind(this, panel));

        // This is not authorized and therefore should not produce any output
        panel.show();
        extension_showPanel("console");

        function handleOpenResource(resource, lineNumber)
        {
            // This will force extension iframe to be really loaded.
            panel.show();
        }
        webInspector.panels.setOpenResourceHandler(handleOpenResource);
        evaluateOnFrontend("WebInspector.openAnchorLocationRegistry._activeHandler = 'test extension'");
        webInspector.inspectedWindow.eval("logMessage()", function() {
            expectOnShown = true;
            evaluateOnFrontend("InspectorTest.clickOnURL();");
        });
    }
    var basePath = location.pathname.replace(/\/[^/]*$/, "/");
    webInspector.panels.create("Test Panel", basePath + "extension-panel.png", basePath + "extension-panel.html", onPanelCreated);
}

function extension_testSearch(nextTest)
{
    var callbackCount = 0;

    function onPanelCreated(panel)
    {
        panel.onSearch.addListener(function(action, queryString) {
            output("Panel searched:");
            dumpObject(Array.prototype.slice.call(arguments));
            callbackCount++;
            if (callbackCount === 2)
                nextTest();
        });

        extension_showPanel("extension");
        evaluateOnFrontend("WebInspector.searchController._performSearch('hello', true, false, true); reply()");
    }
    var basePath = location.pathname.replace(/\/[^/]*$/, "/");
    webInspector.panels.create("Test Panel", basePath + "extension-panel.png", basePath + "non-existent.html", onPanelCreated);
}

function extension_testStatusBarButtons(nextTest)
{
    var basePath = location.pathname.replace(/\/[^/]*$/, "/");

    function onPanelCreated(panel)
    {
        var button1 = panel.createStatusBarButton(basePath + "button1.png", "Button One tooltip");
        var button2 = panel.createStatusBarButton(basePath + "button2.png", "Button Two tooltip", true);
        output("Created a status bar button, dump follows:");
        dumpObject(button1);
        function updateButtons()
        {
            button1.update(basePath + "button1-updated.png");
            button2.update(null, "Button Two updated tooltip", false);
            output("Updated status bar buttons");
            evaluateOnFrontend("InspectorTest.dumpStatusBarButtons(); InspectorTest.clickButton(1);");
        }
        button1.onClicked.addListener(function() {
            output("button1 clicked");
            evaluateOnFrontend("InspectorTest.dumpStatusBarButtons(); reply();", updateButtons);
        });
        button2.onClicked.addListener(function() {
            output("button2 clicked");
            nextTest();
        });
        evaluateOnFrontend("InspectorTest.showPanel('extension'); InspectorTest.clickButton(1); InspectorTest.clickButton(0);", updateButtons);
    }

    webInspector.panels.create("Buttons Panel", basePath + "extension-panel.png", basePath + "non-existent.html", onPanelCreated);
}

</script>
</head>
<body onload="runTest()">
<p>Tests WebInspector extension API</p>
</body>
</html>
