// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

goog.provide('cros.factory.Goofy');

goog.require('goog.debug.ErrorHandler');
goog.require('goog.debug.FancyWindow');
goog.require('goog.debug.Logger');
goog.require('goog.dom');
goog.require('goog.dom.classes');
goog.require('goog.dom.iframe');
goog.require('goog.events');
goog.require('goog.events.EventHandler');
goog.require('goog.json');
goog.require('goog.net.WebSocket');
goog.require('goog.net.XhrIo');
goog.require('goog.string');
goog.require('goog.style');
goog.require('goog.Uri');
goog.require('goog.ui.AdvancedTooltip');
goog.require('goog.ui.Dialog');
goog.require('goog.ui.Dialog.ButtonSet');
goog.require('goog.ui.MenuSeparator');
goog.require('goog.ui.PopupMenu');
goog.require('goog.ui.Select');
goog.require('goog.ui.SplitPane');
goog.require('goog.ui.tree.TreeControl');

cros.factory.logger = goog.debug.Logger.getLogger('cros.factory');

/**
 * @define {boolean} Whether to automatically collapse items once tests have
 *     completed.
 */
cros.factory.AUTO_COLLAPSE = false;

/**
 * Keep-alive interval for the WebSocket.  (Chrome times out
 * WebSockets every ~1 min, so 30 s seems like a good interval.)
 * @const
 * @type number
 */
cros.factory.KEEP_ALIVE_INTERVAL_MSEC = 30000;

/**
 * Width of the control panel, as a fraction of the viewport size.
 * @type number
 */
cros.factory.CONTROL_PANEL_WIDTH_FRACTION = 0.2;

/**
 * Height of the log pane, as a fraction of the viewport size.
 * @type number
 */
cros.factory.LOG_PANE_HEIGHT_FRACTION = 0.2;

/**
 * Makes a label that displays English (or optionally Chinese).
 * @param {string} en
 * @param {string=} zh
 */
cros.factory.Label = function(en, zh) {
    return '<span class="goofy-label-en">' + en + '</span>' +
      '<span class="goofy-label-zh">' + (zh || en) + '</span>';
};

/**
 * Makes control content that displays English (or optionally Chinese).
 * @param {string} en
 * @param {string=} zh
 * @return {Node}
 */
cros.factory.Content = function(en, zh) {
    var span = document.createElement('span');
    span.innerHTML = cros.factory.Label(en, zh);
    return span;
};

/**
 * Labels for items in system info.
 * @type Array.<Object.<string, string>>
 */
cros.factory.SYSTEM_INFO_LABELS = [
    {key: 'serial_number', label: cros.factory.Label('Serial Number')},
    {key: 'factory_image_version',
     label: cros.factory.Label('Factory Image Version')},
    {key: 'wlan0_mac', label: cros.factory.Label('WLAN MAC')},
    {key: 'kernel_version', label: cros.factory.Label('Kernel')},
    {key: 'ec_version', label: cros.factory.Label('EC')},
    {key: 'firmware_version', label: cros.factory.Label('Firmware')},
    {key: 'factory_md5sum', label: cros.factory.Label('Factory MD5SUM'),
     transform: function(value) {
            return value || cros.factory.Label('(no update)')
        }}
                                   ];

cros.factory.UNKNOWN_LABEL = '<span class="goofy-unknown">' +
    cros.factory.Label('Unknown') + '</span>';

/**
 * An item in the test list.
 * @typedef {{path: string, label_en: string, label_zh: string,
 *            kbd_shortcut: string, subtests: Array}}
 */
cros.factory.TestListEntry;

/**
 * Public API for tests.
 * @constructor
 * @param {cros.factory.Invocation} invocation
 */
cros.factory.Test = function(invocation) {
    /**
     * @type cros.factory.Invocation
     */
    this.invocation = invocation;
};

/**
 * Passes the test.
 * @export
 */
cros.factory.Test.prototype.pass = function() {
    this.invocation.goofy.sendEvent(
        'goofy:end_test', {
            'status': 'PASSED',
            'invocation': this.invocation.uuid,
            'test': this.invocation.path
        });
    this.invocation.dispose();
};

/**
 * Fails the test with the given error message.
 * @export
 * @param {string} errorMsg
 */
cros.factory.Test.prototype.fail = function(errorMsg) {
    this.invocation.goofy.sendEvent('goofy:end_test', {
            'status': 'FAILED',
            'error_msg': errorMsg,
            'invocation': this.invocation.uuid,
            'test': this.invocation.path
        });
    this.invocation.dispose();
};

/**
 * Sends an event to the test backend.
 * @export
 * @param {string} subtype the event type
 * @param {string} data the event data
 */
cros.factory.Test.prototype.sendTestEvent = function(subtype, data) {
    this.invocation.goofy.sendEvent('goofy:test_ui_event', {
        'test': this.invocation.path,
        'invocation': this.invocation.uuid,
        'subtype': subtype,
        'data': data
        });
};

/**
 * UI for a single test invocation.
 * @constructor
 * @param {cros.factory.Goofy} goofy
 * @param {string} path
 */
cros.factory.Invocation = function(goofy, path, uuid) {
    /**
     * Reference to the Goofy object.
     * @type cros.factory.Goofy
     */
    this.goofy = goofy;

    /**
     * @type string
     */
    this.path = path;

    /**
     * UUID of the invocation.
     * @type string
     */
    this.uuid = uuid;

    /**
     * Test API for the invocation.
     */
    this.test = new cros.factory.Test(this);

    /**
     * The iframe containing the test.
     * @type HTMLIFrameElement
     */
    this.iframe = goog.dom.iframe.createBlank(new goog.dom.DomHelper(document));
    document.getElementById('goofy-main').appendChild(this.iframe);
    this.iframe.contentWindow.test = this.test;
};

/**
 * Disposes of the invocation (and destroys the iframe).
 */
cros.factory.Invocation.prototype.dispose = function() {
    if (this.iframe) {
        goog.dom.removeNode(this.iframe);
        this.goofy.invocations[this.uuid] = null;
        this.iframe = null;
    }
};

/**
 * The main Goofy UI.
 *
 * @constructor
 */
cros.factory.Goofy = function() {
    /**
     * The WebSocket we'll use to communicate with the backend.
     * @type goog.net.WebSocket
     */
    this.ws = new goog.net.WebSocket();

    /**
     * Whether we have opened the WebSocket yet.
     * @type boolean
     */
    this.wsOpened = false;

    /**
     * The UUID that we received from Goofy when starting up.
     * @type {?string}
     */
    this.uuid = null;

    /**
     * Whether the context menu is currently visible.
     * @type boolean
     */
    this.contextMenuVisible = false;

    /**
     * All tooltips that we have created.
     * @type Array.<goog.ui.AdvancedTooltip>
     */
    this.tooltips = [];

    /**
     * The test tree.
     */
    this.testTree = new goog.ui.tree.TreeControl('Tests');
    this.testTree.setShowRootNode(false);
    this.testTree.setShowLines(false);

    /**
     * A map from test path to the tree node for each test.
     * @type Object.<string, goog.ui.tree.BaseNode>
     */
    this.pathNodeMap = new Object();

    /**
     * A map from test path to the entry in the test list for that test.
     * @type Object.<string, cros.factory.TestListEntry>
     */
    this.pathTestMap = new Object();

    /**
     * Whether Chinese mode is currently enabled.
     *
     * TODO(jsalz): Generalize this to multiple languages (but this isn't
     * really necessary now).
     *
     * @type boolean
     */
    this.zhMode = false;

    /**
     * The tooltip for version number information.
     */
    this.infoTooltip = new goog.ui.AdvancedTooltip(
        document.getElementById('goofy-system-info-hover'));
    this.infoTooltip.setHtml('Version information not yet available.');

    /**
     * UIs for individual test invocations (by UUID).
     * @type Object.<string, cros.factory.Invocation>
     */
    this.invocations = {};

    var debugWindow = new goog.debug.FancyWindow('main');
    debugWindow.setEnabled(false);
    debugWindow.init();
    // Magic keyboard shortcut Ctrl-Alt-1 to open the debugging window.
    goog.events.listen(
        window, goog.events.EventType.KEYDOWN,
        function(event) {
            if (event.altKey && event.ctrlKey &&
                '1' == String.fromCharCode(event.keyCode)) {
                debugWindow.setEnabled(true);
            }
        }, false, this);
};

/**
 * Initializes the split panes.
 */
cros.factory.Goofy.prototype.initSplitPanes = function() {
    var viewportSize = goog.dom.getViewportSize(goog.dom.getWindow(document));
    var mainComponent = new goog.ui.Component();
    var consoleComponent = new goog.ui.Component();
    var mainAndConsole = new goog.ui.SplitPane(
        mainComponent, consoleComponent,
        goog.ui.SplitPane.Orientation.VERTICAL);
    mainAndConsole.setInitialSize(viewportSize.height *
                                  (1 - cros.factory.LOG_PANE_HEIGHT_FRACTION));

    var controlComponent = new goog.ui.Component();
    var topSplitPane = new goog.ui.SplitPane(
        controlComponent, mainAndConsole,
        goog.ui.SplitPane.Orientation.HORIZONTAL);
    topSplitPane.setInitialSize(viewportSize.width *
                                cros.factory.CONTROL_PANEL_WIDTH_FRACTION);
    topSplitPane.decorate(document.getElementById('goofy-splitpane'));

    mainComponent.getElement().id = 'goofy-main';
    consoleComponent.getElement().id = 'goofy-console';
    this.console = consoleComponent.getElement();
    this.main = mainComponent.getElement();

    var propagate = true;
    goog.events.listen(
        topSplitPane, goog.ui.Component.EventType.CHANGE,
        function(event) {
            if (!propagate) {
                // Prevent infinite recursion
                return;
            }

            propagate = false;
            mainAndConsole.setFirstComponentSize(
                mainAndConsole.getFirstComponentSize());
            propagate = true;

            var rect = mainComponent.getElement().getBoundingClientRect();
            this.sendRpc('get_shared_data', ['ui_scale_factor'],
                         function(uiScaleFactor) {
                             this.sendRpc('set_shared_data',
                                          ['test_widget_size',
                                           [rect.width * uiScaleFactor,
                                            rect.height * uiScaleFactor],
                                           'test_widget_position',
                                           [rect.left * uiScaleFactor,
                                            rect.top * uiScaleFactor]]);
                         });
        }, false, this);
    mainAndConsole.setFirstComponentSize(
        mainAndConsole.getFirstComponentSize());
    goog.events.listen(
        window, goog.events.EventType.RESIZE,
        function(event) {
            topSplitPane.setSize(
                goog.dom.getViewportSize(goog.dom.getWindow(document) ||
                                         window));
        });
}

/**
 * Initializes the WebSocket.
 */
cros.factory.Goofy.prototype.initWebSocket = function() {
    goog.events.listen(this.ws, goog.net.WebSocket.EventType.OPENED,
                       function(event) {
                           this.logInternal('Connection to Goofy opened.');
                           this.wsOpened = true;
                       }, false, this);
    goog.events.listen(this.ws, goog.net.WebSocket.EventType.ERROR,
                       function(event) {
                           this.logInternal('Error connecting to Goofy.');
                       }, false, this);
    goog.events.listen(this.ws, goog.net.WebSocket.EventType.CLOSED,
                       function(event) {
                           if (this.wsOpened) {
                               this.logInternal('Connection to Goofy closed.');
                               this.wsOpened = false;
                           }
                       }, false, this);
    goog.events.listen(this.ws, goog.net.WebSocket.EventType.MESSAGE,
                       function(event) {
                           this.handleBackendEvent(event.message);
                       }, false, this);
    window.setInterval(goog.bind(this.keepAlive, this),
                       cros.factory.KEEP_ALIVE_INTERVAL_MSEC);
    this.ws.open("ws://" + window.location.host + "/event");
};

/**
 * Starts the UI.
 */
cros.factory.Goofy.prototype.init = function() {
    this.initLanguageSelector();
    this.initSplitPanes();

    // Listen for keyboard shortcuts.
    goog.events.listen(
        window, goog.events.EventType.KEYDOWN,
        function(event) {
            if (event.altKey || event.ctrlKey) {
                this.handleShortcut(String.fromCharCode(event.keyCode));
            }
        }, false, this);

    this.initWebSocket();
    this.sendRpc('get_test_list', [], this.setTestList);
    this.sendRpc('get_shared_data', ['system_info'], this.setSystemInfo);
};

/**
 * Sets up the language selector.
 */
cros.factory.Goofy.prototype.initLanguageSelector = function() {
    goog.events.listen(
        document.getElementById('goofy-language-selector'),
        goog.events.EventType.CLICK,
        function(event) {
            this.zhMode = !this.zhMode;
            this.updateLanguage();
            this.sendRpc('set_shared_data',
                         ['ui_lang', this.zhMode ? 'zh' : 'en']);
        }, false, this);

    this.updateLanguage();
    this.sendRpc('get_shared_data', ['ui_lang'], function(lang) {
            this.zhMode = lang == 'zh';
            this.updateLanguage();
        });
};

/**
 * Gets an invocation for a test (creating it if necessary).
 *
 * @param {string} path
 * @param {string} invocationUuid
 * @return the invocation, or null if the invocation has already been created
 *     and deleted.
 */
cros.factory.Goofy.prototype.getOrCreateInvocation = function(
    path, invocationUuid) {
    if (!(invocationUuid in this.invocations)) {
        cros.factory.logger.info('Creating UI for test ' + path +
                                 ' (invocation ' + invocationUuid);
        this.invocations[invocationUuid] =
            new cros.factory.Invocation(this, path, invocationUuid);
    }
    return this.invocations[invocationUuid];
};

/**
 * Updates language classes in the UI based on the current value of
 * zhMode.
 */
cros.factory.Goofy.prototype.updateLanguage = function() {
    goog.dom.classes.enable(document.body, 'goofy-lang-en', !this.zhMode);
    goog.dom.classes.enable(document.body, 'goofy-lang-zh', this.zhMode);
}

/**
 * Updates the system info tooltip.
 * @param systemInfo Object.<string, string>
 */
cros.factory.Goofy.prototype.setSystemInfo = function(systemInfo) {
    var table = [];
    table.push('<table id="goofy-system-info">');
    goog.array.forEach(cros.factory.SYSTEM_INFO_LABELS, function(item) {
            var value = systemInfo[item.key];
            var html;
            if (item.transform) {
                html = item.transform(value);
            } else {
                html = value == undefined ?
                    cros.factory.UNKNOWN_LABEL :
                    goog.string.htmlEscape(value);
            }
            table.push(
                       '<tr><th>' + item.label + '</th><td>' + html +
                       '</td></tr>');
        });
    table.push('</table>');
    this.infoTooltip.setHtml(table.join(''));
};

/**
 * Handles a keyboard shortcut.
 * @param {string} key the key that was depressed (e.g., 'a' for Alt-A).
 */
cros.factory.Goofy.prototype.handleShortcut = function(key) {
    for (var path in this.pathTestMap) {
        var test = this.pathTestMap[path];
        if (test.kbd_shortcut &&
            test.kbd_shortcut.toLowerCase() == key.toLowerCase()) {
            this.sendEvent('goofy:restart_tests', {path: path});
            return;
        }
    }
};

/**
 * Makes a menu item for a context-sensitive menu.
 *
 * TODO(jsalz): Figure out the correct logic for this and how to localize this.
 * (Please just consider this a rough cut for now!)
 *
 * @param {string} verbEn the action in English.
 * @param {string} verbZh the action in Chinese.
 * @param {string} adjectiveEn a descriptive adjective for the tests (e.g.,
 *     'failed').
 * @param {string} adjectiveZh the adjective in Chinese.
 * @param {number} count the number of tests.
 * @param {cros.factory.TestListEntry} test the name of the root node containing
 *     the tests.
 * @param {Object} handler the handler function (see goog.events.listen).
 */
cros.factory.Goofy.prototype.makeMenuItem = function(
    verbEn, verbZh, adjectiveEn, adjectiveZh, count, test, handler) {

    var labelEn = verbEn + ' ';
    var labelZh = verbZh;
    if (!test.subtests.length) {
        // leaf node
        labelEn += adjectiveEn + ' test ' + test.label_en;
        labelZh += adjectiveZh + '測試';
    } else {
        labelEn += count + ' ' + adjectiveEn + ' ' +
            (count == 1 ? 'test' : 'tests');
        if (test.label_en) {
            labelEn += ' in "' + goog.string.htmlEscape(test.label_en) + '"';
        }

        labelZh += count + '個' + adjectiveZh;
        if (test.label_en || test.label_zh) {
            labelZh += ('在“' +
                goog.string.htmlEscape(test.label_en || test.label_zh) +
                '”裡面的');
        }
        labelZh += '測試';
    }

    var item = new goog.ui.MenuItem(cros.factory.Content(labelEn, labelZh));
    item.setEnabled(count != 0);
    goog.events.listen(item, goog.ui.Component.EventType.ACTION,
                       handler, true, this);
    return item;
};

/**
 * Displays test logs in a modal dialog.
 * @param {Array.<string>} paths paths whose logs should be displayed.
 *    (The first entry should be the root; its name will be used as the
 *    title.)
 */
cros.factory.Goofy.prototype.showTestLogs = function(paths) {
    this.sendRpc('get_test_history', [paths], function(history) {
        var dialog = new goog.ui.Dialog();

        if (history.length) {
            var viewSize = goog.dom.getViewportSize(
                goog.dom.getWindow(document) || window);
            var maxWidth = viewSize.width * 0.75;
            var maxHeight = viewSize.height * 0.75;

            var content = [
                '<dl class="goofy-history" style="max-width: ' +
                maxWidth + 'px; max-height: ' + maxHeight + 'px">'
                           ];
            goog.array.forEach(history, function(item) {
                content.push('<dt class="goofy-history-item history-item-' +
                             item.state.status +
                             '">' + goog.string.htmlEscape(item.path) +
                             ' (run ' +
                             item.state.count + ')</dt>');
                content.push('<dd>' + goog.string.htmlEscape(item.log) +
                             '</dd>');
            }, this);
            content.push('</dl>');
            dialog.setContent(content.join(''));
        } else {
            dialog.setContent('<div class="goofy-history-none">' +
                              'No test runs have completed yet.</div>');
        }
        dialog.setTitle(
            'Logs for ' + (paths[0] == '' ? 'all tests' :
                           '"' + goog.string.htmlEscape(paths[0]) + '"'));
        dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createOk())
        dialog.setVisible(true);
    });
};

/**
 * Displays a context menu for a test in the test tree.
 * @param {string} path the path of the test whose context menu should be
 *     displayed.
 * @param {Element} labelElement the label element of the node in the test
 *     tree.
 * @param {Array.<goog.ui.Control>=} extraItems items to prepend to the
 *     menu.
 */
cros.factory.Goofy.prototype.showTestPopup = function(path, labelElement,
                                                      extraItems) {
    this.contextMenuVisible = true;
    // Hide all tooltips so that they don't fight with the context menu.
    goog.array.forEach(this.tooltips, function(tooltip) {
            tooltip.setVisible(false);
        });

    var menu = new goog.ui.PopupMenu();

    if (extraItems && extraItems.length) {
        goog.array.forEach(extraItems, function(item) {
                menu.addChild(item, true);
            }, this);
        menu.addChild(new goog.ui.MenuSeparator(), true);
    }

    var numLeaves = 0;
    var numLeavesByStatus = {};
    var test = this.pathTestMap[path];
    var allPaths = [];
    function countLeaves(test) {
        allPaths.push(test.path);
        goog.array.forEach(test.subtests, function(subtest) {
                countLeaves(subtest);
            }, this);

        if (!test.subtests.length) {
            ++numLeaves;
            numLeavesByStatus[test.state.status] = 1 + (
                numLeavesByStatus[test.state.status] || 0);
        }
    }
    countLeaves(test);

    var restartOrRunEn = numLeavesByStatus['UNTESTED'] == numLeaves ?
        'Run' : 'Restart';
    var restartOrRunZh = numLeavesByStatus['UNTESTED'] == numLeaves ?
        '執行' : '重跑';
    if (numLeaves > 1) {
        restartOrRunEn += ' all';
        restartOrRunZh += '所有的';
    }
    menu.addChild(this.makeMenuItem(restartOrRunEn, restartOrRunZh,
                                    '', '',
                                    numLeaves, test,
                                    function(event) {
        this.sendEvent('goofy:restart_tests', {'path': path});
    }), true);
    if (test.subtests.length) {
        // Only show for parents.
        menu.addChild(this.makeMenuItem(
            'Restart', '重跑', 'failed', '已失敗的',
            numLeavesByStatus['FAILED'] || 0,
            test, function(event) {
                this.sendEvent('goofy:re_run_failed', {'path': path});
            }), true);
        menu.addChild(this.makeMenuItem(
            'Run', '執行', 'untested', '未測的',
            (numLeavesByStatus['UNTESTED'] || 0 +
             numLeavesByStatus['ACTIVE'] || 0),
            test, function(event) {
                this.sendEvent('goofy:auto_run', {'path': path});
            }), true);
    }
    menu.addChild(new goog.ui.MenuSeparator(), true);
    // TODO(jsalz): This isn't quite right since it stops all tests.
    // But close enough for now.
    menu.addChild(this.makeMenuItem('Stop', '停止', 'active', '正在跑的',
                                    numLeavesByStatus['ACTIVE'] || 0,
                                    test, function(event) {
        this.sendEvent('goofy:stop');
    }), true);

    var item = new goog.ui.MenuItem('Show test logs...');
    item.setEnabled(test.state.status != 'UNTESTED');
    goog.events.listen(item, goog.ui.Component.EventType.ACTION,
                       function(event) {
                           this.showTestLogs(allPaths);
                       }, true, this);
    // Disable 'Show test logs...' for now since it is presented
    // behind the running test; we'd need to hide test to show it
    // properly.  TODO(jsalz): Re-enable.
    // menu.addChild(item, true);

    menu.render(document.body);
    menu.showAtElement(labelElement,
                     goog.positioning.Corner.BOTTOM_LEFT,
                     goog.positioning.Corner.TOP_LEFT);
    goog.events.listen(menu, goog.ui.Component.EventType.HIDE,
                       function(event) {
                           menu.dispose();
                           this.contextMenuVisible = false;
                       }, true, this);
};

/**
 * Updates the tooltip for a test based on its status.
 * The tooltip will be displayed only for failed tests.
 * @param {string} path
 * @param {goog.ui.AdvancedTooltip} tooltip
 * @param {goog.events.Event} event the BEFORE_SHOW event that will cause the
 *     tooltip to be displayed.
 */
cros.factory.Goofy.prototype.updateTestToolTip =
    function(path, tooltip, event) {
    var test = this.pathTestMap[path];

    tooltip.setHtml('')

    var errorMsg = test.state['error_msg'];
    if (test.state.status != 'FAILED' || this.contextMenuVisible || !errorMsg) {
        // Don't bother showing it.
        event.preventDefault();
    } else {
        // Show the last failure.
        var lines = errorMsg.split('\n');
        var html = ('Failure in "' + test.label_en + '":' +
                    '<div class="goofy-test-failure">' +
                    goog.string.htmlEscape(lines.shift()) + '</span>');

        if (lines.length) {
            html += ('<div class="goofy-test-failure-detail-link">' +
                     'Show more detail...</div>' +
                     '<div class="goofy-test-failure-detail">' +
                     goog.string.htmlEscape(lines.join('\n')) + '</div>');
        }

        tooltip.setHtml(html);

        if (lines.length) {
            var link = goog.dom.getElementByClass(
            'goofy-test-failure-detail-link', tooltip.getElement());
            goog.events.listen(
                link, goog.events.EventType.CLICK,
                function(event) {
                    goog.dom.classes.add(tooltip.getElement(),
                                         'goofy-test-failure-expanded');
                    tooltip.reposition();
            }, true, this);
        }
    }
};

/**
 * Sets up the UI for a the test list.  (Should be invoked only once, when
 * the test list is received.)
 * @param {cros.factory.TestListEntry} testList the test list (the return value
 *     of the get_test_list RPC call).
 */
cros.factory.Goofy.prototype.setTestList = function(testList) {
    cros.factory.logger.info('Received test list: ' +
        goog.debug.expose(testList));
    goog.style.showElement(document.getElementById('goofy-loading'), false);

    this.addToNode(null, testList);
    // expandAll is necessary to get all the elements to actually be
    // created right away so we can add listeners.  We'll collapse it later.
    this.testTree.expandAll();
    this.testTree.render(document.getElementById('goofy-test-tree'));

    var addListener = goog.bind(function(path, labelElement, rowElement) {
        var tooltip = new goog.ui.AdvancedTooltip(rowElement);
        tooltip.setHideDelayMs(1000);
        this.tooltips.push(tooltip);
        goog.events.listen(
            tooltip, goog.ui.Component.EventType.BEFORE_SHOW,
            function(event) {
                this.updateTestToolTip(path, tooltip, event);
            }, true, this)
        goog.events.listen(
            rowElement, goog.events.EventType.CONTEXTMENU,
            function(event) {
                this.showTestPopup(path, labelElement);
                event.stopPropagation();
                event.preventDefault();
            }, true, this);
        goog.events.listen(
            labelElement, goog.events.EventType.MOUSEDOWN,
            function(event) {
                this.showTestPopup(path, labelElement);
                event.stopPropagation();
                event.preventDefault();
            }, true, this);
    }, this);

    for (var path in this.pathNodeMap) {
        var node = this.pathNodeMap[path];
        addListener(path, node.getLabelElement(), node.getRowElement());
    }

    goog.array.forEach([goog.events.EventType.MOUSEDOWN,
                        goog.events.EventType.CONTEXTMENU],
        function(eventType) {
            goog.events.listen(
                document.getElementById('goofy-title'),
                eventType,
                function(event) {
                    var updateItem = new goog.ui.MenuItem(
                        cros.factory.Content('Update factory software',
                                             '更新工廠軟體'));
                    goog.events.listen(
                        updateItem, goog.ui.Component.EventType.ACTION,
                        function(event) {
                            this.sendEvent('goofy:update_factory', {});
                        }, true, this);

                    this.showTestPopup(
                        '', document.getElementById('goofy-logo-text'),
                        [updateItem]);

                    event.stopPropagation();
                    event.preventDefault();
                }, true, this);
        }, this);

    this.testTree.collapseAll();
    this.sendRpc('get_test_states', [], function(stateMap) {
        for (var path in stateMap) {
            if (!goog.string.startsWith(path, "_")) {  // e.g., __jsonclass__
                this.setTestState(path, stateMap[path]);
            }
        }
    });
};

/**
 * Sets the state for a particular test.
 * @param {string} path
 * @param {Object.<string, Object>} state the TestState object (contained in
 *     an event or as a response to the RPC call).
 */
cros.factory.Goofy.prototype.setTestState = function(path, state) {
    var node = this.pathNodeMap[path];
    if (!node) {
        cros.factory.logger.warning('No node found for test path ' + path);
        return;
    }

    var elt = this.pathNodeMap[path].getElement();
    var test = this.pathTestMap[path];
    test.state = state;

    // Assign the appropriate class to the node, and remove all other
    // status classes.
    goog.dom.classes.addRemove(
        elt,
        goog.array.filter(
            goog.dom.classes.get(elt),
            function(cls) {
                return goog.string.startsWith(cls, "goofy-status-") && cls
            }),
        'goofy-status-' + state.status.toLowerCase());

    if (state.status == 'ACTIVE') {
        // Automatically show the test if it is running.
        node.reveal();
    } else if (cros.factory.AUTO_COLLAPSE) {
        // If collapsible, then collapse it in 250ms if still inactive.
        if (node.getChildCount() != 0) {
            window.setTimeout(function(event) {
                    if (test.state.status != 'ACTIVE') {
                        node.collapse();
                    }
                }, 250);
        }
    }
};

/**
 * Adds a test node to the tree.
 * @param {goog.ui.tree.BaseNode} parent
 * @param {cros.factory.TestListEntry} test
 */
cros.factory.Goofy.prototype.addToNode = function(parent, test) {
    var node;
    if (parent == null) {
        node = this.testTree;
    } else {
        var label = '<span class="goofy-label-en">' +
            goog.string.htmlEscape(test.label_en) + '</span>';
        label += '<span class="goofy-label-zh">' +
            goog.string.htmlEscape(test.label_zh || test.label_en) + '</span>';
        if (test.kbd_shortcut) {
            label = '<span class="goofy-kbd-shortcut">Alt-' +
                goog.string.htmlEscape(test.kbd_shortcut.toUpperCase()) +
                '</span>' + label;
        }
        node = this.testTree.createNode(label);
        parent.addChild(node);
    }
    goog.array.forEach(test.subtests, function(subtest) {
            this.addToNode(node, subtest);
        }, this);

    node.setIconClass('goofy-test-icon');
    node.setExpandedIconClass('goofy-test-icon');

    this.pathNodeMap[test.path] = node;
    this.pathTestMap[test.path] = test;
    node.factoryTest = test;
};

/**
 * Sends an event to Goofy.
 * @param {string} type the event type (e.g., 'goofy:hello').
 * @param {Object} properties of event.
 */
cros.factory.Goofy.prototype.sendEvent = function(type, properties) {
    var dict = goog.object.clone(properties);
    dict.type = type;
    var serialized = goog.json.serialize(dict);
    cros.factory.logger.info('Sending event: ' + serialized);
    this.ws.send(serialized);
};

/**
 * Calls an RPC function and invokes callback with the result.
 * @param {Object} args
 * @param {Object=} callback
 */
cros.factory.Goofy.prototype.sendRpc = function(method, args, callback) {
    var request = goog.json.serialize({method: method, params: args, id: 1});
    cros.factory.logger.info('RPC request: ' + request);
    var factoryThis = this;
    goog.net.XhrIo.send(
        '/', function() {
            cros.factory.logger.info('RPC response for ' + method + ': ' +
                                     this.getResponseText());
            // TODO(jsalz): handle errors
            if (callback) {
                callback.call(
                    factoryThis,
                    goog.json.unsafeParse(this.getResponseText()).result);
            }
        },
        'POST', request);
};

/**
 * Sends a keepalive event if the web socket is open.
 */
cros.factory.Goofy.prototype.keepAlive = function() {
    if (this.ws.isOpen()) {
        this.sendEvent('goofy:keepalive', {'uuid': this.uuid});
    }
};

/**
 * Writes a message to the console log.
 * @param {string} message
 * @param {Object|Array.<string>|string=} opt_attributes attributes to add
 *     to the div element containing the log entry.
 */
cros.factory.Goofy.prototype.logToConsole = function(message, opt_attributes) {
    var div = goog.dom.createDom('div', opt_attributes);
    goog.dom.classes.add(div, 'goofy-log-line');
    div.appendChild(document.createTextNode(message));
    this.console.appendChild(div);
    // Scroll to bottom.  TODO(jsalz): Scroll only if already at the bottom,
    // or add scroll lock.
    var scrollPane = goog.dom.getAncestorByClass(this.console,
        'goog-splitpane-second-container');
    scrollPane.scrollTop = scrollPane.scrollHeight;
};

/**
 * Logs an "internal" message to the console (as opposed to a line from
 * console.log).
 */
cros.factory.Goofy.prototype.logInternal = function(message) {
    this.logToConsole(message, 'goofy-internal-log');
};

/**
 * Handles an event sends from the backend.
 * @param {string} jsonMessage the message as a JSON string.
 */
cros.factory.Goofy.prototype.handleBackendEvent = function(jsonMessage) {
    cros.factory.logger.info('Got message: ' + jsonMessage);
    var message = /** @type Object.<string, Object> */ (
        goog.json.unsafeParse(jsonMessage));

    if (message.type == 'goofy:hello') {
        if (this.uuid && message.uuid != this.uuid) {
            // The goofy process has changed; reload the page.
            cros.factory.logger.info('Incorrect UUID; reloading');
            window.location.reload();
            return;
        } else {
            this.uuid = message.uuid;
            // Send a keepAlive to confirm the UUID with the backend.
            this.keepAlive();
            // TODO(jsalz): Process version number information.
        }
    } else if (message.type == 'goofy:log') {
        this.logToConsole(message.message);
    } else if (message.type == 'goofy:state_change') {
        this.setTestState(message.path, message.state);
    } else if (message.type == 'goofy:set_html') {
        var invocation = this.getOrCreateInvocation(
            message.test, message.invocation);
        if (invocation) {
            invocation.iframe.contentDocument.body.innerHTML = message['html'];
        }
    } else if (message.type == 'goofy:run_js') {
        var invocation = this.getOrCreateInvocation(
            message.test, message.invocation);
        if (invocation) {
            invocation.iframe.contentWindow.eval(
                /** @type string */ (message['js']));
        }
    } else if (message.type == 'goofy:call_js_function') {
        var invocation = this.getOrCreateInvocation(
            message.test, message.invocation);
        if (invocation) {
            var func = invocation.iframe.contentWindow[message['name']];
            if (func) {
                func.apply(this, message['args']);
            } else {
                cros.factory.logger.severe('Unable to find function ' + func +
                                           ' in UI for test ' + message.test);
            }
        }
    } else if (message.type == 'goofy:destroy_test') {
        var invocation = this.invocations[message.invocation];
        if (invocation) {
            invocation.dispose();
        }
    } else if (message.type == 'goofy:system_info') {
        this.setSystemInfo(message['system_info']);
    }
};

goog.events.listenOnce(window, goog.events.EventType.LOAD, function() {
        window.goofy = new cros.factory.Goofy();
        window.goofy.init();
    });
