/*
 * 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.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());
})();
