/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

// Use IIFE to avoid leaking names to other scripts.
(function () {

function getTimeInMs() {
    return new Date().getTime();
}

class TimeLog {
    constructor() {
        this.start = getTimeInMs();
    }

    log(name) {
        let end = getTimeInMs();
        console.log(name, end - this.start, 'ms');
        this.start = end;
    }
}

class ProgressBar {
    constructor() {
        let str = `
            <div class="modal" tabindex="-1" role="dialog">
                <div class="modal-dialog" role="document">
                    <div class="modal-content">
                        <div class="modal-header"><h5 class="modal-title">Loading page...</h5></div>
                        <div class="modal-body">
                            <div class="progress">
                                <div class="progress-bar" role="progressbar"
                                    style="width: 0%" aria-valuenow="0" aria-valuemin="0"
                                    aria-valuemax="100">0%</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        `;
        this.modal = $(str).appendTo($('body'));
        this.progress = 0;
        this.shownCallback = null;
        this.modal.on('shown.bs.modal', () => this._onShown());
        // Shorten progress bar update time.
        this.modal.find('.progress-bar').css('transition-duration', '0ms');
        this.shown = false;
    }

    // progress is [0-100]. Return a Promise resolved when the update is shown.
    updateAsync(text, progress) {
        progress = parseInt(progress);  // Truncate float number to integer.
        return this.showAsync().then(() => {
            if (text) {
                this.modal.find('.modal-title').text(text);
            }
            this.progress = progress;
            this.modal.find('.progress-bar').css('width', progress + '%')
                    .attr('aria-valuenow', progress).text(progress + '%');
            // Leave 100ms for the progess bar to update.
            return createPromise((resolve) => setTimeout(resolve, 100));
        });
    }

    showAsync() {
        if (this.shown) {
            return createPromise();
        }
        return createPromise((resolve) => {
            this.shownCallback = resolve;
            this.modal.modal({
                show: true,
                keyboard: false,
                backdrop: false,
            });
        });
    }

    _onShown() {
        this.shown = true;
        if (this.shownCallback) {
            let callback = this.shownCallback;
            this.shownCallback = null;
            callback();
        }
    }

    hide() {
        this.shown = false;
        this.modal.modal('hide');
    }
}

function openHtml(name, attrs={}) {
    let s = `<${name} `;
    for (let key in attrs) {
        s += `${key}="${attrs[key]}" `;
    }
    s += '>';
    return s;
}

function closeHtml(name) {
    return `</${name}>`;
}

function getHtml(name, attrs={}) {
    let text;
    if ('text' in attrs) {
        text = attrs.text;
        delete attrs.text;
    }
    let s = openHtml(name, attrs);
    if (text) {
        s += text;
    }
    s += closeHtml(name);
    return s;
}

function getTableRow(cols, colName, attrs={}) {
    let s = openHtml('tr', attrs);
    for (let col of cols) {
        s += `<${colName}>${col}</${colName}>`;
    }
    s += '</tr>';
    return s;
}

function getProcessName(pid) {
    let name = gProcesses[pid];
    return name ? `${pid} (${name})`: pid.toString();
}

function getThreadName(tid) {
    let name = gThreads[tid];
    return name ? `${tid} (${name})`: tid.toString();
}

function getLibName(libId) {
    return gLibList[libId];
}

function getFuncName(funcId) {
    return gFunctionMap[funcId].f;
}

function getLibNameOfFunction(funcId) {
    return getLibName(gFunctionMap[funcId].l);
}

function getFuncSourceRange(funcId) {
    let func = gFunctionMap[funcId];
    if (func.hasOwnProperty('s')) {
        return {fileId: func.s[0], startLine: func.s[1], endLine: func.s[2]};
    }
    return null;
}

function getFuncDisassembly(funcId) {
    let func = gFunctionMap[funcId];
    return func.hasOwnProperty('d') ? func.d : null;
}

function getSourceFilePath(sourceFileId) {
    return gSourceFiles[sourceFileId].path;
}

function getSourceCode(sourceFileId) {
    return gSourceFiles[sourceFileId].code;
}

function isClockEvent(eventInfo) {
    return eventInfo.eventName.includes('task-clock') ||
            eventInfo.eventName.includes('cpu-clock');
}

let createId = function() {
    let currentId = 0;
    return () => `id${++currentId}`;
}();

class TabManager {
    constructor(divContainer) {
        let id = createId();
        divContainer.append(`<ul class="nav nav-pills mb-3 mt-3 ml-3" id="${id}" role="tablist">
            </ul><hr/><div class="tab-content" id="${id}Content"></div>`);
        this.ul = divContainer.find(`#${id}`);
        this.content = divContainer.find(`#${id}Content`);
        // Map from title to [tabObj, drawn=false|true].
        this.tabs = new Map();
        this.tabActiveCallback = null;
    }

    addTab(title, tabObj) {
        let id = createId();
        this.content.append(`<div class="tab-pane" id="${id}" role="tabpanel"
            aria-labelledby="${id}-tab"></div>`);
        this.ul.append(`
            <li class="nav-item">
                <a class="nav-link" id="${id}-tab" data-toggle="pill" href="#${id}" role="tab"
                    aria-controls="${id}" aria-selected="false">${title}</a>
            </li>`);
        tabObj.init(this.content.find(`#${id}`));
        this.tabs.set(title, [tabObj, false]);
        this.ul.find(`#${id}-tab`).on('shown.bs.tab', () => this.onTabActive(title));
        return tabObj;
    }

    setActiveAsync(title) {
        let tabObj = this.findTab(title);
        return createPromise((resolve) => {
            this.tabActiveCallback = resolve;
            let id = tabObj.div.attr('id') + '-tab';
            this.ul.find(`#${id}`).tab('show');
        });
    }

    onTabActive(title) {
        let array = this.tabs.get(title);
        let tabObj = array[0];
        let drawn = array[1];
        if (!drawn) {
            tabObj.draw();
            array[1] = true;
        }
        if (this.tabActiveCallback) {
            let callback = this.tabActiveCallback;
            this.tabActiveCallback = null;
            callback();
        }
    }

    findTab(title) {
        let array = this.tabs.get(title);
        return array ? array[0] : null;
    }
}

function createEventTabs(id) {
    let ul = `<ul class="nav nav-pills mb-3 mt-3 ml-3" id="${id}" role="tablist">`;
    let content = `<div class="tab-content" id="${id}Content">`;
    for (let i = 0; i < gSampleInfo.length; ++i) {
        let subId = id + '_' + i;
        let title = gSampleInfo[i].eventName;
        ul += `
            <li class="nav-item">
                <a class="nav-link" id="${subId}-tab" data-toggle="pill" href="#${subId}" role="tab"
                aria-controls="${subId}" aria-selected="${i == 0 ? "true" : "false"}">${title}</a>
            </li>`;
        content += `
            <div class="tab-pane" id="${subId}" role="tabpanel" aria-labelledby="${subId}-tab">
            </div>`;
    }
    ul += '</ul>';
    content += '</div>';
    return ul + content;
}

function createViewsForEvents(div, createViewCallback) {
    let views = [];
    if (gSampleInfo.length == 1) {
        views.push(createViewCallback(div, gSampleInfo[0]));
    } else if (gSampleInfo.length > 1) {
        // If more than one event, draw them in tabs.
        let id = createId();
        div.append(createEventTabs(id));
        for (let i = 0; i < gSampleInfo.length; ++i) {
            let subId = id + '_' + i;
            views.push(createViewCallback(div.find(`#${subId}`), gSampleInfo[i]));
        }
        div.find(`#${id}_0-tab`).tab('show');
    }
    return views;
}

// Return a promise to draw views.
function drawViewsAsync(views, totalProgress, drawViewCallback) {
    if (views.length == 0) {
        return createPromise();
    }
    let drawPos = 0;
    let eachProgress = totalProgress / views.length;
    function drawAsync() {
        if (drawPos == views.length) {
            return createPromise();
        }
        return drawViewCallback(views[drawPos++], eachProgress).then(drawAsync);
    }
    return drawAsync();
}

// Show global information retrieved from the record file, including:
//   record time
//   machine type
//   Android version
//   record cmdline
//   total samples
class RecordFileView {
    constructor(divContainer) {
        this.div = $('<div>');
        this.div.appendTo(divContainer);
    }

    draw() {
        google.charts.setOnLoadCallback(() => this.realDraw());
    }

    realDraw() {
        this.div.empty();
        // Draw a table of 'Name', 'Value'.
        let rows = [];
        if (gRecordInfo.recordTime) {
            rows.push(['Record Time', gRecordInfo.recordTime]);
        }
        if (gRecordInfo.machineType) {
            rows.push(['Machine Type', gRecordInfo.machineType]);
        }
        if (gRecordInfo.androidVersion) {
            rows.push(['Android Version', gRecordInfo.androidVersion]);
        }
        if (gRecordInfo.androidBuildFingerprint) {
            rows.push(['Build Fingerprint', gRecordInfo.androidBuildFingerprint]);
        }
        if (gRecordInfo.kernelVersion) {
            rows.push(['Kernel Version', gRecordInfo.kernelVersion]);
        }
        if (gRecordInfo.recordCmdline) {
            rows.push(['Record cmdline', gRecordInfo.recordCmdline]);
        }
        rows.push(['Total Samples', '' + gRecordInfo.totalSamples]);

        let data = new google.visualization.DataTable();
        data.addColumn('string', '');
        data.addColumn('string', '');
        data.addRows(rows);
        for (let i = 0; i < rows.length; ++i) {
            data.setProperty(i, 0, 'className', 'boldTableCell');
        }
        let table = new google.visualization.Table(this.div.get(0));
        table.draw(data, {
            width: '100%',
            sort: 'disable',
            allowHtml: true,
            cssClassNames: {
                'tableCell': 'tableCell',
            },
        });
    }
}

// Show pieChart of event count percentage of each process, thread, library and function.
class ChartView {
    constructor(divContainer, eventInfo) {
        this.div = $('<div>').appendTo(divContainer);
        this.eventInfo = eventInfo;
        this.processInfo = null;
        this.threadInfo = null;
        this.libInfo = null;
        this.states = {
            SHOW_EVENT_INFO: 1,
            SHOW_PROCESS_INFO: 2,
            SHOW_THREAD_INFO: 3,
            SHOW_LIB_INFO: 4,
        };
        if (isClockEvent(this.eventInfo)) {
            this.getSampleWeight = function (eventCount) {
                return (eventCount / 1000000.0).toFixed(3) + ' ms';
            };
        } else {
            this.getSampleWeight = (eventCount) => '' + eventCount;
        }
    }

    _getState() {
        if (this.libInfo) {
            return this.states.SHOW_LIB_INFO;
        }
        if (this.threadInfo) {
            return this.states.SHOW_THREAD_INFO;
        }
        if (this.processInfo) {
            return this.states.SHOW_PROCESS_INFO;
        }
        return this.states.SHOW_EVENT_INFO;
    }

    _goBack() {
        let state = this._getState();
        if (state == this.states.SHOW_PROCESS_INFO) {
            this.processInfo = null;
        } else if (state == this.states.SHOW_THREAD_INFO) {
            this.threadInfo = null;
        } else if (state == this.states.SHOW_LIB_INFO) {
            this.libInfo = null;
        }
        this.draw();
    }

    _selectHandler(chart) {
        let selectedItem = chart.getSelection()[0];
        if (selectedItem) {
            let state = this._getState();
            if (state == this.states.SHOW_EVENT_INFO) {
                this.processInfo = this.eventInfo.processes[selectedItem.row];
            } else if (state == this.states.SHOW_PROCESS_INFO) {
                this.threadInfo = this.processInfo.threads[selectedItem.row];
            } else if (state == this.states.SHOW_THREAD_INFO) {
                this.libInfo = this.threadInfo.libs[selectedItem.row];
            }
            this.draw();
        }
    }

    draw() {
        google.charts.setOnLoadCallback(() => this.realDraw());
    }

    realDraw() {
        this.div.empty();
        this._drawTitle();
        this._drawPieChart();
    }

    _drawTitle() {
        // Draw a table of 'Name', 'Event Count'.
        let rows = [];
        rows.push(['Event Type: ' + this.eventInfo.eventName,
                   this.getSampleWeight(this.eventInfo.eventCount)]);
        if (this.processInfo) {
            rows.push(['Process: ' + getProcessName(this.processInfo.pid),
                       this.getSampleWeight(this.processInfo.eventCount)]);
        }
        if (this.threadInfo) {
            rows.push(['Thread: ' + getThreadName(this.threadInfo.tid),
                       this.getSampleWeight(this.threadInfo.eventCount)]);
        }
        if (this.libInfo) {
            rows.push(['Library: ' + getLibName(this.libInfo.libId),
                       this.getSampleWeight(this.libInfo.eventCount)]);
        }
        let data = new google.visualization.DataTable();
        data.addColumn('string', '');
        data.addColumn('string', '');
        data.addRows(rows);
        for (let i = 0; i < rows.length; ++i) {
            data.setProperty(i, 0, 'className', 'boldTableCell');
        }
        let wrapperDiv = $('<div>');
        wrapperDiv.appendTo(this.div);
        let table = new google.visualization.Table(wrapperDiv.get(0));
        table.draw(data, {
            width: '100%',
            sort: 'disable',
            allowHtml: true,
            cssClassNames: {
                'tableCell': 'tableCell',
            },
        });
        if (this._getState() != this.states.SHOW_EVENT_INFO) {
            $('<button type="button" class="btn btn-primary">Back</button>').appendTo(this.div)
                .click(() => this._goBack());
        }
    }

    _drawPieChart() {
        let state = this._getState();
        let title = null;
        let firstColumn = null;
        let rows = [];
        let thisObj = this;
        function getItem(name, eventCount, totalEventCount) {
            let sampleWeight = thisObj.getSampleWeight(eventCount);
            let percent = (eventCount * 100.0 / totalEventCount).toFixed(2) + '%';
            return [name, eventCount, getHtml('pre', {text: name}) +
                        getHtml('b', {text: `${sampleWeight} (${percent})`})];
        }

        if (state == this.states.SHOW_EVENT_INFO) {
            title = 'Processes in event type ' + this.eventInfo.eventName;
            firstColumn = 'Process';
            for (let process of this.eventInfo.processes) {
                rows.push(getItem('Process: ' + getProcessName(process.pid), process.eventCount,
                                  this.eventInfo.eventCount));
            }
        } else if (state == this.states.SHOW_PROCESS_INFO) {
            title = 'Threads in process ' + getProcessName(this.processInfo.pid);
            firstColumn = 'Thread';
            for (let thread of this.processInfo.threads) {
                rows.push(getItem('Thread: ' + getThreadName(thread.tid), thread.eventCount,
                                  this.processInfo.eventCount));
            }
        } else if (state == this.states.SHOW_THREAD_INFO) {
            title = 'Libraries in thread ' + getThreadName(this.threadInfo.tid);
            firstColumn = 'Library';
            for (let lib of this.threadInfo.libs) {
                rows.push(getItem('Library: ' + getLibName(lib.libId), lib.eventCount,
                                  this.threadInfo.eventCount));
            }
        } else if (state == this.states.SHOW_LIB_INFO) {
            title = 'Functions in library ' + getLibName(this.libInfo.libId);
            firstColumn = 'Function';
            for (let func of this.libInfo.functions) {
                rows.push(getItem('Function: ' + getFuncName(func.f), func.c[1],
                                  this.libInfo.eventCount));
            }
        }
        let data = new google.visualization.DataTable();
        data.addColumn('string', firstColumn);
        data.addColumn('number', 'EventCount');
        data.addColumn({type: 'string', role: 'tooltip', p: {html: true}});
        data.addRows(rows);

        let wrapperDiv = $('<div>');
        wrapperDiv.appendTo(this.div);
        let chart = new google.visualization.PieChart(wrapperDiv.get(0));
        chart.draw(data, {
            title: title,
            width: 1000,
            height: 600,
            tooltip: {isHtml: true},
        });
        google.visualization.events.addListener(chart, 'select', () => this._selectHandler(chart));
    }
}


class ChartStatTab {
    init(div) {
        this.div = div;
    }

    draw() {
        new RecordFileView(this.div).draw();
        let views = createViewsForEvents(this.div, (div, eventInfo) => {
            return new ChartView(div, eventInfo);
        });
        for (let view of views) {
            view.draw();
        }
    }
}


class SampleTableTab {
    init(div) {
        this.div = div;
    }

    draw() {
        let views = [];
        createPromise()
            .then(updateProgress('Draw SampleTable...', 0))
            .then(wait(() => {
                this.div.empty();
                views = createViewsForEvents(this.div, (div, eventInfo) => {
                    return new SampleTableView(div, eventInfo);
                });
            }))
            .then(() => drawViewsAsync(views, 100, (view, progress) => view.drawAsync(progress)))
            .then(hideProgress());
    }
}

// Select the way to show sample weight in SampleTableTab.
// 1. Show percentage of event count.
// 2. Show event count (For cpu-clock and task-clock events, it is time in ms).
class SampleTableWeightSelectorView {
    constructor(divContainer, eventInfo, onSelectChange) {
        let options = new Map();
        options.set('percent', 'Show percentage of event count');
        options.set('event_count', 'Show event count');
        if (isClockEvent(eventInfo)) {
            options.set('event_count_in_ms', 'Show event count in milliseconds');
        }
        let buttons = [];
        options.forEach((value, key) => {
            buttons.push(`<button type="button" class="dropdown-item" key="${key}">${value}
                          </button>`);
        });
        this.curOption = 'percent';
        this.eventCount = eventInfo.eventCount;
        let id = createId();
        let str = `
            <div class="dropdown">
                <button type="button" class="btn btn-primary dropdown-toggle" id="${id}"
                    data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
                    >${options.get(this.curOption)}</button>
                <div class="dropdown-menu" aria-labelledby="${id}">${buttons.join('')}</div>
            </div>
        `;
        divContainer.append(str);
        divContainer.children().last().on('hidden.bs.dropdown', (e) => {
            if (e.clickEvent) {
                let button = $(e.clickEvent.target);
                let newOption = button.attr('key');
                if (newOption && this.curOption != newOption) {
                    this.curOption = newOption;
                    divContainer.find(`#${id}`).text(options.get(this.curOption));
                    onSelectChange();
                }
            }
        });
    }

    getSampleWeightFunction() {
        if (this.curOption == 'percent') {
            return (eventCount) => (eventCount * 100.0 / this.eventCount).toFixed(2) + '%';
        }
        if (this.curOption == 'event_count') {
            return (eventCount) => '' + eventCount;
        }
        if (this.curOption == 'event_count_in_ms') {
            return (eventCount) => (eventCount / 1000000.0).toFixed(3);
        }
    }

    getSampleWeightSuffix() {
        if (this.curOption == 'event_count_in_ms') {
            return ' ms';
        }
        return '';
    }
}


class SampleTableView {
    constructor(divContainer, eventInfo) {
        this.id = createId();
        this.div = $('<div>', {id: this.id}).appendTo(divContainer);
        this.eventInfo = eventInfo;
        this.selectorView = null;
        this.tableDiv = null;
    }

    drawAsync(totalProgress) {
        return createPromise()
            .then(wait(() => {
                this.div.empty();
                this.selectorView = new SampleTableWeightSelectorView(
                    this.div, this.eventInfo, () => this.onSampleWeightChange());
                this.tableDiv = $('<div>').appendTo(this.div);
            }))
            .then(() => this._drawSampleTable(totalProgress));
    }

    // Return a promise to draw SampleTable.
    _drawSampleTable(totalProgress) {
        let eventInfo = this.eventInfo;
        let data = [];
        return createPromise()
            .then(wait(() => {
                this.tableDiv.empty();
                let getSampleWeight = this.selectorView.getSampleWeightFunction();
                let sampleWeightSuffix = this.selectorView.getSampleWeightSuffix();
                // Draw a table of 'Total', 'Self', 'Samples', 'Process', 'Thread', 'Library',
                // 'Function'.
                let valueSuffix = sampleWeightSuffix.length > 0 ? `(in${sampleWeightSuffix})` : '';
                let titles = ['Total' + valueSuffix, 'Self' + valueSuffix, 'Samples', 'Process',
                              'Thread', 'Library', 'Function', 'HideKey'];
                this.tableDiv.append(`
                    <table cellspacing="0" class="table table-striped table-bordered"
                        style="width:100%">
                        <thead>${getTableRow(titles, 'th')}</thead>
                        <tbody></tbody>
                        <tfoot>${getTableRow(titles, 'th')}</tfoot>
                    </table>`);
                for (let [i, process] of eventInfo.processes.entries()) {
                    let processName = getProcessName(process.pid);
                    for (let [j, thread] of process.threads.entries()) {
                        let threadName = getThreadName(thread.tid);
                        for (let [k, lib] of thread.libs.entries()) {
                            let libName = getLibName(lib.libId);
                            for (let [t, func] of lib.functions.entries()) {
                                let totalValue = getSampleWeight(func.c[2]);
                                let selfValue = getSampleWeight(func.c[1]);
                                let key = [i, j, k, t].join('_');
                                data.push([totalValue, selfValue, func.c[0], processName,
                                           threadName, libName, getFuncName(func.f), key])
                           }
                        }
                    }
                }
            }))
            .then(addProgress(totalProgress / 2))
            .then(wait(() => {
                let table = this.tableDiv.find('table');
                let dataTable = table.DataTable({
                    lengthMenu: [10, 20, 50, 100, -1],
                    order: [0, 'desc'],
                    data: data,
                    responsive: true,
                });
                dataTable.column(7).visible(false);

                table.find('tr').css('cursor', 'pointer');
                table.on('click', 'tr', function() {
                    let data = dataTable.row(this).data();
                    if (!data) {
                        // A row in header or footer.
                        return;
                    }
                    let key = data[7];
                    if (!key) {
                        return;
                    }
                    let indexes = key.split('_');
                    let processInfo = eventInfo.processes[indexes[0]];
                    let threadInfo = processInfo.threads[indexes[1]];
                    let lib = threadInfo.libs[indexes[2]];
                    let func = lib.functions[indexes[3]];
                    FunctionTab.showFunction(eventInfo, processInfo, threadInfo, lib, func);
                });
            }));
    }

    onSampleWeightChange() {
        createPromise()
            .then(updateProgress('Draw SampleTable...', 0))
            .then(() => this._drawSampleTable(100))
            .then(hideProgress());
    }
}


// Show embedded flamegraph generated by inferno.
class FlameGraphTab {
    init(div) {
        this.div = div;
    }

    draw() {
        let views = [];
        createPromise()
            .then(updateProgress('Draw Flamegraph...', 0))
            .then(wait(() => {
                this.div.empty();
                views = createViewsForEvents(this.div, (div, eventInfo) => {
                    return new FlameGraphViewList(div, eventInfo);
                });
            }))
            .then(() => drawViewsAsync(views, 100, (view, progress) => view.drawAsync(progress)))
            .then(hideProgress());
    }
}

// Show FlameGraphs for samples in an event type, used in FlameGraphTab.
// 1. Draw 10 FlameGraphs at one time, and use a "More" button to show more FlameGraphs.
// 2. First draw background of Flamegraphs, then draw details in idle time.
class FlameGraphViewList {
    constructor(div, eventInfo) {
        this.div = div;
        this.eventInfo = eventInfo;
        this.selectorView = null;
        this.flamegraphDiv = null;
        this.flamegraphs = [];
        this.moreButton = null;
    }

    drawAsync(totalProgress) {
        this.div.empty();
        this.selectorView = new SampleWeightSelectorView(this.div, this.eventInfo,
                                                         () => this.onSampleWeightChange());
        this.flamegraphDiv = $('<div>').appendTo(this.div);
        return this._drawMoreFlameGraphs(10, totalProgress);
    }

    // Return a promise to draw flamegraphs.
    _drawMoreFlameGraphs(moreCount, progress) {
        let initProgress = progress / (1 + moreCount);
        let newFlamegraphs = [];
        return createPromise()
        .then(wait(() => {
            if (this.moreButton) {
                this.moreButton.hide();
            }
            let pId = 0;
            let tId = 0;
            let newCount = this.flamegraphs.length + moreCount;
            for (let i = 0; i < newCount; ++i) {
                if (pId == this.eventInfo.processes.length) {
                    break;
                }
                let process = this.eventInfo.processes[pId];
                let thread = process.threads[tId];
                if (i >= this.flamegraphs.length) {
                    let title = `Process ${getProcessName(process.pid)} ` +
                                `Thread ${getThreadName(thread.tid)} ` +
                                `(Samples: ${thread.sampleCount})`;
                    let totalCount = {countForProcess: process.eventCount,
                                      countForThread: thread.eventCount};
                    let flamegraph = new FlameGraphView(this.flamegraphDiv, title, totalCount,
                                                        thread.g.c, false);
                    flamegraph.draw();
                    newFlamegraphs.push(flamegraph);
                }
                tId++;
                if (tId == process.threads.length) {
                    pId++;
                    tId = 0;
                }
            }
            if (pId < this.eventInfo.processes.length) {
                // Show "More" Button.
                if (!this.moreButton) {
                    this.div.append(`
                        <div style="text-align:center">
                            <button type="button" class="btn btn-primary">More</button>
                        </div>`);
                    this.moreButton = this.div.children().last().find('button');
                    this.moreButton.click(() => {
                        createPromise().then(updateProgress('Draw FlameGraph...', 0))
                            .then(() => this._drawMoreFlameGraphs(10, 100))
                            .then(hideProgress());
                    });
                    this.moreButton.hide();
                }
            } else if (this.moreButton) {
                this.moreButton.remove();
                this.moreButton = null;
            }
            for (let flamegraph of newFlamegraphs) {
                this.flamegraphs.push(flamegraph);
            }
        }))
        .then(addProgress(initProgress))
        .then(() => this.drawDetails(newFlamegraphs, progress - initProgress));
    }

    drawDetails(flamegraphs, totalProgress) {
        return createPromise()
            .then(() => drawViewsAsync(flamegraphs, totalProgress, (view, progress) => {
                return createPromise()
                    .then(wait(() => view.drawDetails(this.selectorView.getSampleWeightFunction())))
                    .then(addProgress(progress));
            }))
            .then(wait(() => {
               if (this.moreButton) {
                   this.moreButton.show();
               }
            }));
    }

    onSampleWeightChange() {
        createPromise().then(updateProgress('Draw FlameGraph...', 0))
            .then(() => this.drawDetails(this.flamegraphs, 100))
            .then(hideProgress());
    }
}

// FunctionTab: show information of a function.
// 1. Show the callgrpah and reverse callgraph of a function as flamegraphs.
// 2. Show the annotated source code of the function.
class FunctionTab {
    static showFunction(eventInfo, processInfo, threadInfo, lib, func) {
        let title = 'Function';
        let tab = gTabs.findTab(title);
        if (!tab) {
            tab = gTabs.addTab(title, new FunctionTab());
        }
        gTabs.setActiveAsync(title)
            .then(() => tab.setFunction(eventInfo, processInfo, threadInfo, lib, func));
    }

    constructor() {
        this.func = null;
        this.selectPercent = 'thread';
    }

    init(div) {
        this.div = div;
    }

    setFunction(eventInfo, processInfo, threadInfo, lib, func) {
        this.eventInfo = eventInfo;
        this.processInfo = processInfo;
        this.threadInfo = threadInfo;
        this.lib = lib;
        this.func = func;
        this.selectorView = null;
        this.views = [];
        this.redraw();
    }

    redraw() {
        if (!this.func) {
            return;
        }
        createPromise()
            .then(updateProgress("Draw Function...", 0))
            .then(wait(() => {
                this.div.empty();
                this._drawTitle();

                this.selectorView = new SampleWeightSelectorView(this.div, this.eventInfo,
                                                                 () => this.onSampleWeightChange());
                let funcId = this.func.f;
                let funcName = getFuncName(funcId);
                function getNodesMatchingFuncId(root) {
                    let nodes = [];
                    function recursiveFn(node) {
                        if (node.f == funcId) {
                            nodes.push(node);
                        } else {
                            for (let child of node.c) {
                                recursiveFn(child);
                            }
                        }
                    }
                    recursiveFn(root);
                    return nodes;
                }
                let totalCount = {countForProcess: this.processInfo.eventCount,
                                  countForThread: this.threadInfo.eventCount};
                let callgraphView = new FlameGraphView(
                    this.div, `Functions called by ${funcName}`, totalCount,
                    getNodesMatchingFuncId(this.threadInfo.g), false);
                callgraphView.draw();
                this.views.push(callgraphView);
                let reverseCallgraphView = new FlameGraphView(
                    this.div, `Functions calling ${funcName}`, totalCount,
                    getNodesMatchingFuncId(this.threadInfo.rg), true);
                reverseCallgraphView.draw();
                this.views.push(reverseCallgraphView);
                let sourceFiles = collectSourceFilesForFunction(this.func);
                if (sourceFiles) {
                    this.div.append(getHtml('hr'));
                    this.div.append(getHtml('b', {text: 'SourceCode:'}) + '<br/>');
                    this.views.push(new SourceCodeView(this.div, sourceFiles, totalCount));
                }

                let disassembly = collectDisassemblyForFunction(this.func);
                if (disassembly) {
                    this.div.append(getHtml('hr'));
                    this.div.append(getHtml('b', {text: 'Disassembly:'}) + '<br/>');
                    this.views.push(new DisassemblyView(this.div, disassembly, totalCount));
                }
            }))
            .then(addProgress(25))
            .then(() => this.drawDetails(75))
            .then(hideProgress());
    }

    draw() {}

    _drawTitle() {
        let eventName = this.eventInfo.eventName;
        let processName = getProcessName(this.processInfo.pid);
        let threadName = getThreadName(this.threadInfo.tid);
        let libName = getLibName(this.lib.libId);
        let funcName = getFuncName(this.func.f);
        // Draw a table of 'Name', 'Value'.
        let rows = [];
        rows.push(['Event Type', eventName]);
        rows.push(['Process', processName]);
        rows.push(['Thread', threadName]);
        rows.push(['Library', libName]);
        rows.push(['Function', getHtml('pre', {text: funcName})]);
        let data = new google.visualization.DataTable();
        data.addColumn('string', '');
        data.addColumn('string', '');
        data.addRows(rows);
        for (let i = 0; i < rows.length; ++i) {
            data.setProperty(i, 0, 'className', 'boldTableCell');
        }
        let wrapperDiv = $('<div>');
        wrapperDiv.appendTo(this.div);
        let table = new google.visualization.Table(wrapperDiv.get(0));
        table.draw(data, {
            width: '100%',
            sort: 'disable',
            allowHtml: true,
            cssClassNames: {
                'tableCell': 'tableCell',
            },
        });
    }

    onSampleWeightChange() {
        createPromise()
            .then(updateProgress("Draw Function...", 0))
            .then(() => this.drawDetails(100))
            .then(hideProgress());
    }

    drawDetails(totalProgress) {
        let sampleWeightFunction = this.selectorView.getSampleWeightFunction();
        return drawViewsAsync(this.views, totalProgress, (view, progress) => {
            return createPromise()
                .then(wait(() => view.drawDetails(sampleWeightFunction)))
                .then(addProgress(progress));
        });
    }
}


// Select the way to show sample weight in FlamegraphTab and FunctionTab.
// 1. Show percentage of event count relative to all processes.
// 2. Show percentage of event count relative to the current process.
// 3. Show percentage of event count relative to the current thread.
// 4. Show absolute event count.
// 5. Show event count in milliseconds, only possible for cpu-clock or task-clock events.
class SampleWeightSelectorView {
    constructor(divContainer, eventInfo, onSelectChange) {
        let options = new Map();
        options.set('percent_to_all', 'Show percentage of event count relative to all processes');
        options.set('percent_to_process',
                    'Show percentage of event count relative to the current process');
        options.set('percent_to_thread',
                    'Show percentage of event count relative to the current thread');
        options.set('event_count', 'Show event count');
        if (isClockEvent(eventInfo)) {
            options.set('event_count_in_ms', 'Show event count in milliseconds');
        }
        let buttons = [];
        options.forEach((value, key) => {
            buttons.push(`<button type="button" class="dropdown-item" key="${key}">${value}
                          </button>`);
        });
        this.curOption = 'percent_to_all';
        let id = createId();
        let str = `
            <div class="dropdown">
                <button type="button" class="btn btn-primary dropdown-toggle" id="${id}"
                    data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
                    >${options.get(this.curOption)}</button>
                <div class="dropdown-menu" aria-labelledby="${id}">${buttons.join('')}</div>
            </div>
        `;
        divContainer.append(str);
        divContainer.children().last().on('hidden.bs.dropdown', (e) => {
            if (e.clickEvent) {
                let button = $(e.clickEvent.target);
                let newOption = button.attr('key');
                if (newOption && this.curOption != newOption) {
                    this.curOption = newOption;
                    divContainer.find(`#${id}`).text(options.get(this.curOption));
                    onSelectChange();
                }
            }
        });
        this.countForAllProcesses = eventInfo.eventCount;
    }

    getSampleWeightFunction() {
        if (this.curOption == 'percent_to_all') {
            let countForAllProcesses = this.countForAllProcesses;
            return function(eventCount, _) {
                let percent = eventCount * 100.0 / countForAllProcesses;
                return percent.toFixed(2) + '%';
            };
        }
        if (this.curOption == 'percent_to_process') {
            return function(eventCount, totalCount) {
                let percent = eventCount * 100.0 / totalCount.countForProcess;
                return percent.toFixed(2) + '%';
            };
        }
        if (this.curOption == 'percent_to_thread') {
            return function(eventCount, totalCount) {
                let percent = eventCount * 100.0 / totalCount.countForThread;
                return percent.toFixed(2) + '%';
            };
        }
        if (this.curOption == 'event_count') {
            return function(eventCount, _) {
                return '' + eventCount;
            };
        }
        if (this.curOption == 'event_count_in_ms') {
            return function(eventCount, _) {
                let timeInMs = eventCount / 1000000.0;
                return timeInMs.toFixed(3) + ' ms';
            };
        }
    }
}

// Given a callgraph, show the flamegraph.
class FlameGraphView {
    constructor(divContainer, title, totalCount, initNodes, reverseOrder) {
        this.id = createId();
        this.div = $('<div>', {id: this.id,
                               style: 'font-family: Monospace; font-size: 12px'});
        this.div.appendTo(divContainer);
        this.title = title;
        this.totalCount = totalCount;
        this.reverseOrder = reverseOrder;
        this.sampleWeightFunction = null;
        this.svgNodeHeight = 17;
        this.initNodes = initNodes;
        this.sumCount = 0;
        for (let node of initNodes) {
            this.sumCount += node.s;
        }
        this.maxDepth = this._getMaxDepth(this.initNodes);
        this.svgHeight = this.svgNodeHeight * (this.maxDepth + 3);
        this.svgStr = null;
        this.svgDiv = null;
        this.svg = null;
    }

    _getMaxDepth(nodes) {
        let isArray = Array.isArray(nodes);
        let sumCount;
        if (isArray) {
            sumCount = nodes.reduce((acc, cur) => acc + cur.s, 0);
        } else {
            sumCount = nodes.s;
        }
        let width = this._getWidthPercentage(sumCount);
        if (width < 0.1) {
            return 0;
        }
        let children = isArray ? this._splitChildrenForNodes(nodes) : nodes.c;
        let childDepth = 0;
        for (let child of children) {
            childDepth = Math.max(childDepth, this._getMaxDepth(child));
        }
        return childDepth + 1;
    }

    draw() {
        // Only draw skeleton.
        this.div.empty();
        this.div.append(`<p><b>${this.title}</b></p>`);
        this.svgStr = [];
        this._renderBackground();
        this.svgStr.push('</svg></div>');
        this.div.append(this.svgStr.join(''));
        this.svgDiv = this.div.children().last();
        this.div.append('<br/><br/>');
    }

    drawDetails(sampleWeightFunction) {
        this.sampleWeightFunction = sampleWeightFunction;
        this.svgStr = [];
        this._renderBackground();
        this._renderSvgNodes();
        this._renderUnzoomNode();
        this._renderInfoNode();
        this._renderPercentNode();
        this._renderSearchNode();
        // It is much faster to add html content to svgStr than adding it directly to svgDiv.
        this.svgDiv.html(this.svgStr.join(''));
        this.svgStr = [];
        this.svg = this.svgDiv.find('svg');
        this._adjustTextSize();
        this._enableZoom();
        this._enableInfo();
        this._enableSearch();
        this._adjustTextSizeOnResize();
    }

    _renderBackground() {
        this.svgStr.push(`
            <div style="width: 100%; height: ${this.svgHeight}px;">
                <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                    version="1.1" width="100%" height="100%" style="border: 1px solid black; ">
                        <defs > <linearGradient id="background_gradient_${this.id}"
                                  y1="0" y2="1" x1="0" x2="0" >
                                  <stop stop-color="#eeeeee" offset="5%" />
                                  <stop stop-color="#efefb1" offset="90%" />
                                  </linearGradient>
                         </defs>
                         <rect x="0" y="0" width="100%" height="100%"
                           fill="url(#background_gradient_${this.id})" />`);
    }

    _getYForDepth(depth) {
        if (this.reverseOrder) {
            return (depth + 3) * this.svgNodeHeight;
        }
        return this.svgHeight - (depth + 1) * this.svgNodeHeight;
    }

    _getWidthPercentage(eventCount) {
        return eventCount * 100.0 / this.sumCount;
    }

    _getHeatColor(widthPercentage) {
        return {
            r: Math.floor(245 + 10 * (1 - widthPercentage * 0.01)),
            g: Math.floor(110 + 105 * (1 - widthPercentage * 0.01)),
            b: 100,
        };
    }

    _renderSvgNodes() {
        let fakeNodes = [{c: this.initNodes}];
        let children = this._splitChildrenForNodes(fakeNodes);
        let xOffset = 0;
        for (let child of children) {
            xOffset = this._renderSvgNodesWithSameRoot(child, 0, xOffset);
        }
    }

    // Return an array of children nodes, with children having the same functionId merged in a
    // subarray.
    _splitChildrenForNodes(nodes) {
        let map = new Map();
        for (let node of nodes) {
            for (let child of node.c) {
                let subNodes = map.get(child.f);
                if (subNodes) {
                    subNodes.push(child);
                } else {
                    map.set(child.f, [child]);
                }
            }
        }
        let res = [];
        for (let subNodes of map.values()) {
            res.push(subNodes.length == 1 ? subNodes[0] : subNodes);
        }
        return res;
    }

    // nodes can be a CallNode, or an array of CallNodes with the same functionId.
    _renderSvgNodesWithSameRoot(nodes, depth, xOffset) {
        let x = xOffset;
        let y = this._getYForDepth(depth);
        let isArray = Array.isArray(nodes);
        let funcId;
        let sumCount;
        if (isArray) {
            funcId = nodes[0].f;
            sumCount = nodes.reduce((acc, cur) => acc + cur.s, 0);
        } else {
            funcId = nodes.f;
            sumCount = nodes.s;
        }
        let width = this._getWidthPercentage(sumCount);
        if (width < 0.1) {
            return xOffset;
        }
        let color = this._getHeatColor(width);
        let borderColor = {};
        for (let key in color) {
            borderColor[key] = Math.max(0, color[key] - 50);
        }
        let funcName = getFuncName(funcId);
        let libName = getLibNameOfFunction(funcId);
        let sampleWeight = this.sampleWeightFunction(sumCount, this.totalCount);
        let title = funcName + ' | ' + libName + ' (' + sumCount + ' events: ' +
                    sampleWeight + ')';
        this.svgStr.push(`<g><title>${title}</title> <rect x="${x}%" y="${y}" ox="${x}"
                        depth="${depth}" width="${width}%" owidth="${width}" height="15.0"
                        ofill="rgb(${color.r},${color.g},${color.b})"
                        fill="rgb(${color.r},${color.g},${color.b})"
                        style="stroke:rgb(${borderColor.r},${borderColor.g},${borderColor.b})"/>
                        <text x="${x}%" y="${y + 12}"></text></g>`);

        let children = isArray ? this._splitChildrenForNodes(nodes) : nodes.c;
        let childXOffset = xOffset;
        for (let child of children) {
            childXOffset = this._renderSvgNodesWithSameRoot(child, depth + 1, childXOffset);
        }
        return xOffset + width;
    }

    _renderUnzoomNode() {
        this.svgStr.push(`<rect id="zoom_rect_${this.id}" style="display:none;stroke:rgb(0,0,0);"
        rx="10" ry="10" x="10" y="10" width="80" height="30"
        fill="rgb(255,255,255)"/>
         <text id="zoom_text_${this.id}" x="19" y="30" style="display:none">Zoom out</text>`);
    }

    _renderInfoNode() {
        this.svgStr.push(`<clipPath id="info_clip_path_${this.id}">
                         <rect style="stroke:rgb(0,0,0);" rx="10" ry="10" x="120" y="10"
                         width="789" height="30" fill="rgb(255,255,255)"/>
                         </clipPath>
                         <rect style="stroke:rgb(0,0,0);" rx="10" ry="10" x="120" y="10"
                         width="799" height="30" fill="rgb(255,255,255)"/>
                         <text clip-path="url(#info_clip_path_${this.id})"
                         id="info_text_${this.id}" x="128" y="30"></text>`);
    }

    _renderPercentNode() {
        this.svgStr.push(`<rect style="stroke:rgb(0,0,0);" rx="10" ry="10"
                         x="934" y="10" width="150" height="30"
                         fill="rgb(255,255,255)"/>
                         <text id="percent_text_${this.id}" text-anchor="end"
                         x="1074" y="30"></text>`);
    }

    _renderSearchNode() {
        this.svgStr.push(`<rect style="stroke:rgb(0,0,0); rx="10" ry="10"
                         x="1150" y="10" width="80" height="30"
                         fill="rgb(255,255,255)" class="search"/>
                         <text x="1160" y="30" class="search">Search</text>`);
    }

    _adjustTextSizeForNode(g) {
        let text = g.find('text');
        let width = parseFloat(g.find('rect').attr('width')) * this.svgWidth * 0.01;
        if (width < 28) {
            text.text('');
            return;
        }
        let methodName = g.find('title').text().split(' | ')[0];
        let numCharacters;
        for (numCharacters = methodName.length; numCharacters > 4; numCharacters--) {
            if (numCharacters * 7.5 <= width) {
                break;
            }
        }
        if (numCharacters == methodName.length) {
            text.text(methodName);
        } else {
            text.text(methodName.substring(0, numCharacters - 2) + '..');
        }
    }

    _adjustTextSize() {
        this.svgWidth = $(window).width();
        let thisObj = this;
        this.svg.find('g').each(function(_, g) {
            thisObj._adjustTextSizeForNode($(g));
        });
    }

    _enableZoom() {
        this.zoomStack = [null];
        this.svg.find('g').css('cursor', 'pointer').click(zoom);
        this.svg.find(`#zoom_rect_${this.id}`).css('cursor', 'pointer').click(unzoom);
        this.svg.find(`#zoom_text_${this.id}`).css('cursor', 'pointer').click(unzoom);

        let thisObj = this;
        function zoom() {
            thisObj.zoomStack.push(this);
            displayFromElement(this);
            thisObj.svg.find(`#zoom_rect_${thisObj.id}`).css('display', 'block');
            thisObj.svg.find(`#zoom_text_${thisObj.id}`).css('display', 'block');
        }

        function unzoom() {
            if (thisObj.zoomStack.length > 1) {
                thisObj.zoomStack.pop();
                displayFromElement(thisObj.zoomStack[thisObj.zoomStack.length - 1]);
                if (thisObj.zoomStack.length == 1) {
                    thisObj.svg.find(`#zoom_rect_${thisObj.id}`).css('display', 'none');
                    thisObj.svg.find(`#zoom_text_${thisObj.id}`).css('display', 'none');
                }
            }
        }

        function displayFromElement(g) {
            let clickedOriginX = 0;
            let clickedDepth = 0;
            let clickedOriginWidth = 100;
            let scaleFactor = 1;
            if (g) {
                g = $(g);
                let clickedRect = g.find('rect');
                clickedOriginX = parseFloat(clickedRect.attr('ox'));
                clickedDepth = parseInt(clickedRect.attr('depth'));
                clickedOriginWidth = parseFloat(clickedRect.attr('owidth'));
                scaleFactor = 100.0 / clickedOriginWidth;
            }
            thisObj.svg.find('g').each(function(_, g) {
                g = $(g);
                let text = g.find('text');
                let rect = g.find('rect');
                let depth = parseInt(rect.attr('depth'));
                let ox = parseFloat(rect.attr('ox'));
                let owidth = parseFloat(rect.attr('owidth'));
                if (depth < clickedDepth || ox < clickedOriginX - 1e-9 ||
                    ox + owidth > clickedOriginX + clickedOriginWidth + 1e-9) {
                    rect.css('display', 'none');
                    text.css('display', 'none');
                } else {
                    rect.css('display', 'block');
                    text.css('display', 'block');
                    let nx = (ox - clickedOriginX) * scaleFactor + '%';
                    let ny = thisObj._getYForDepth(depth - clickedDepth);
                    rect.attr('x', nx);
                    rect.attr('y', ny);
                    rect.attr('width', owidth * scaleFactor + '%');
                    text.attr('x', nx);
                    text.attr('y', ny + 12);
                    thisObj._adjustTextSizeForNode(g);
                }
            });
        }
    }

    _enableInfo() {
        this.selected = null;
        let thisObj = this;
        this.svg.find('g').on('mouseenter', function() {
            if (thisObj.selected) {
                thisObj.selected.css('stroke-width', '0');
            }
            // Mark current node.
            let g = $(this);
            thisObj.selected = g;
            g.css('stroke', 'black').css('stroke-width', '0.5');

            // Parse title.
            let title = g.find('title').text();
            let methodAndInfo = title.split(' | ');
            thisObj.svg.find(`#info_text_${thisObj.id}`).text(methodAndInfo[0]);

            // Parse percentage.
            // '/system/lib64/libhwbinder.so (4 events: 0.28%)'
            let regexp = /.* \(.*:\s+(.*)\)/g;
            let match = regexp.exec(methodAndInfo[1]);
            let percentage = '';
            if (match && match.length > 1) {
                percentage = match[1];
            }
            thisObj.svg.find(`#percent_text_${thisObj.id}`).text(percentage);
        });
    }

    _enableSearch() {
        this.svg.find('.search').css('cursor', 'pointer').click(() => {
            let term = prompt('Search for:', '');
            if (!term) {
                this.svg.find('g > rect').each(function() {
                    this.attributes['fill'].value = this.attributes['ofill'].value;
                });
            } else {
                this.svg.find('g').each(function() {
                    let title = this.getElementsByTagName('title')[0];
                    let rect = this.getElementsByTagName('rect')[0];
                    if (title.textContent.indexOf(term) != -1) {
                        rect.attributes['fill'].value = 'rgb(230,100,230)';
                    } else {
                        rect.attributes['fill'].value = rect.attributes['ofill'].value;
                    }
                });
            }
        });
    }

    _adjustTextSizeOnResize() {
        function throttle(callback) {
            let running = false;
            return function() {
                if (!running) {
                    running = true;
                    window.requestAnimationFrame(function () {
                        callback();
                        running = false;
                    });
                }
            };
        }
        $(window).resize(throttle(() => this._adjustTextSize()));
    }
}


class SourceFile {

    constructor(fileId) {
        this.path = getSourceFilePath(fileId);
        this.code = getSourceCode(fileId);
        this.showLines = {};  // map from line number to {eventCount, subtreeEventCount}.
        this.hasCount = false;
    }

    addLineRange(startLine, endLine) {
        for (let i = startLine; i <= endLine; ++i) {
            if (i in this.showLines || !(i in this.code)) {
                continue;
            }
            this.showLines[i] = {eventCount: 0, subtreeEventCount: 0};
        }
    }

    addLineCount(lineNumber, eventCount, subtreeEventCount) {
        let line = this.showLines[lineNumber];
        if (line) {
            line.eventCount += eventCount;
            line.subtreeEventCount += subtreeEventCount;
            this.hasCount = true;
        }
    }
}

// Return a list of SourceFile related to a function.
function collectSourceFilesForFunction(func) {
    if (!func.hasOwnProperty('s')) {
        return null;
    }
    let hitLines = func.s;
    let sourceFiles = {};  // map from sourceFileId to SourceFile.

    function getFile(fileId) {
        let file = sourceFiles[fileId];
        if (!file) {
            file = sourceFiles[fileId] = new SourceFile(fileId);
        }
        return file;
    }

    // Show lines for the function.
    let funcRange = getFuncSourceRange(func.f);
    if (funcRange) {
        let file = getFile(funcRange.fileId);
        file.addLineRange(funcRange.startLine);
    }

    // Show lines for hitLines.
    for (let hitLine of hitLines) {
        let file = getFile(hitLine.f);
        file.addLineRange(hitLine.l - 5, hitLine.l + 5);
        file.addLineCount(hitLine.l, hitLine.e, hitLine.s);
    }

    let result = [];
    // Show the source file containing the function before other source files.
    if (funcRange) {
        let file = getFile(funcRange.fileId);
        if (file.hasCount) {
            result.push(file);
        }
        delete sourceFiles[funcRange.fileId];
    }
    for (let fileId in sourceFiles) {
        let file = sourceFiles[fileId];
        if (file.hasCount) {
            result.push(file);
        }
    }
    return result.length > 0 ? result : null;
}

// Show annotated source code of a function.
class SourceCodeView {

    constructor(divContainer, sourceFiles, totalCount) {
        this.div = $('<div>');
        this.div.appendTo(divContainer);
        this.sourceFiles = sourceFiles;
        this.totalCount = totalCount;
    }

    drawDetails(sampleWeightFunction) {
        google.charts.setOnLoadCallback(() => this.realDraw(sampleWeightFunction));
    }

    realDraw(sampleWeightFunction) {
        this.div.empty();
        // For each file, draw a table of 'Line', 'Total', 'Self', 'Code'.
        for (let sourceFile of this.sourceFiles) {
            let rows = [];
            let lineNumbers = Object.keys(sourceFile.showLines);
            lineNumbers.sort((a, b) => a - b);
            for (let lineNumber of lineNumbers) {
                let code = getHtml('pre', {text: sourceFile.code[lineNumber]});
                let countInfo = sourceFile.showLines[lineNumber];
                let totalValue = '';
                let selfValue = '';
                if (countInfo.subtreeEventCount != 0) {
                    totalValue = sampleWeightFunction(countInfo.subtreeEventCount, this.totalCount);
                    selfValue = sampleWeightFunction(countInfo.eventCount, this.totalCount);
                }
                rows.push([lineNumber, totalValue, selfValue, code]);
            }

            let data = new google.visualization.DataTable();
            data.addColumn('string', 'Line');
            data.addColumn('string', 'Total');
            data.addColumn('string', 'Self');
            data.addColumn('string', 'Code');
            data.addRows(rows);
            for (let i = 0; i < rows.length; ++i) {
                data.setProperty(i, 0, 'className', 'colForLine');
                for (let j = 1; j <= 2; ++j) {
                    data.setProperty(i, j, 'className', 'colForCount');
                }
            }
            this.div.append(getHtml('pre', {text: sourceFile.path}));
            let wrapperDiv = $('<div>');
            wrapperDiv.appendTo(this.div);
            let table = new google.visualization.Table(wrapperDiv.get(0));
            table.draw(data, {
                width: '100%',
                sort: 'disable',
                frozenColumns: 3,
                allowHtml: true,
            });
        }
    }
}

// Return a list of disassembly related to a function.
function collectDisassemblyForFunction(func) {
    if (!func.hasOwnProperty('a')) {
        return null;
    }
    let hitAddrs = func.a;
    let rawCode = getFuncDisassembly(func.f);
    if (!rawCode) {
        return null;
    }

    // Annotate disassembly with event count information.
    let annotatedCode = [];
    let codeForLastAddr = null;
    let hitAddrPos = 0;
    let hasCount = false;

    function addEventCount(addr) {
        while (hitAddrPos < hitAddrs.length && BigInt(hitAddrs[hitAddrPos].a) < addr) {
            if (codeForLastAddr) {
                codeForLastAddr.eventCount += hitAddrs[hitAddrPos].e;
                codeForLastAddr.subtreeEventCount += hitAddrs[hitAddrPos].s;
                hasCount = true;
            }
            hitAddrPos++;
        }
    }

    for (let line of rawCode) {
        let code = line[0];
        let addr = BigInt(line[1]);

        addEventCount(addr);
        let item = {code: code, eventCount: 0, subtreeEventCount: 0};
        annotatedCode.push(item);
        // Objdump sets addr to 0 when a disassembly line is not associated with an addr.
        if (addr != 0) {
            codeForLastAddr = item;
        }
    }
    addEventCount(Number.MAX_VALUE);
    return hasCount ? annotatedCode : null;
}

// Show annotated disassembly of a function.
class DisassemblyView {

    constructor(divContainer, disassembly, totalCount) {
        this.div = $('<div>');
        this.div.appendTo(divContainer);
        this.disassembly = disassembly;
        this.totalCount = totalCount;
    }

    drawDetails(sampleWeightFunction) {
        google.charts.setOnLoadCallback(() => this.realDraw(sampleWeightFunction));
    }

    realDraw(sampleWeightFunction) {
        this.div.empty();
        // Draw a table of 'Total', 'Self', 'Code'.
        let rows = [];
        for (let line of this.disassembly) {
            let code = getHtml('pre', {text: line.code});
            let totalValue = '';
            let selfValue = '';
            if (line.subtreeEventCount != 0) {
                totalValue = sampleWeightFunction(line.subtreeEventCount, this.totalCount);
                selfValue = sampleWeightFunction(line.eventCount, this.totalCount);
            }
            rows.push([totalValue, selfValue, code]);
        }
        let data = new google.visualization.DataTable();
        data.addColumn('string', 'Total');
        data.addColumn('string', 'Self');
        data.addColumn('string', 'Code');
        data.addRows(rows);
        for (let i = 0; i < rows.length; ++i) {
            for (let j = 0; j < 2; ++j) {
                data.setProperty(i, j, 'className', 'colForCount');
            }
        }
        let wrapperDiv = $('<div>');
        wrapperDiv.appendTo(this.div);
        let table = new google.visualization.Table(wrapperDiv.get(0));
        table.draw(data, {
            width: '100%',
            sort: 'disable',
            frozenColumns: 2,
            allowHtml: true,
        });
    }
}


function initGlobalObjects() {
    let recordData = $('#record_data').text();
    gRecordInfo = JSON.parse(recordData);
    gProcesses = gRecordInfo.processNames;
    gThreads = gRecordInfo.threadNames;
    gLibList = gRecordInfo.libList;
    gFunctionMap = gRecordInfo.functionMap;
    gSampleInfo = gRecordInfo.sampleInfo;
    gSourceFiles = gRecordInfo.sourceFiles;
}

function createTabs() {
    gTabs = new TabManager($('div#report_content'));
    gTabs.addTab('Chart Statistics', new ChartStatTab());
    gTabs.addTab('Sample Table', new SampleTableTab());
    gTabs.addTab('Flamegraph', new FlameGraphTab());
}

// Global draw objects
let gTabs;
let gProgressBar = new ProgressBar();

// Gobal Json Data
let gRecordInfo;
let gProcesses;
let gThreads;
let gLibList;
let gFunctionMap;
let gSampleInfo;
let gSourceFiles;

function updateProgress(text, progress) {
    return () => gProgressBar.updateAsync(text, progress);
}

function addProgress(progress) {
    return () => gProgressBar.updateAsync(null, gProgressBar.progress + progress);
}

function hideProgress() {
    return () => gProgressBar.hide();
}

function createPromise(callback) {
    if (callback) {
        return new Promise((resolve, _) => callback(resolve));
    }
    return new Promise((resolve,_) => resolve());
}

function waitDocumentReady() {
    return createPromise((resolve) => $(document).ready(resolve));
}

function wait(functionCall) {
    return () => {
        functionCall();
        return createPromise();
    };
}

createPromise()
    .then(updateProgress('Load page...', 0))
    .then(waitDocumentReady)
    .then(updateProgress('Parse Json data...', 20))
    .then(wait(initGlobalObjects))
    .then(updateProgress('Create tabs...', 30))
    .then(wait(createTabs))
    .then(updateProgress('Draw ChartStat...', 40))
    .then(() => gTabs.setActiveAsync('Chart Statistics'))
    .then(updateProgress(null, 100))
    .then(hideProgress());
})();
