<!DOCTYPE html>
<!--
Copyright (c) 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<link rel="import" href="/base/units/util.html">
<link rel="import" href="/core/selection.html">
<link rel="import" href="/base/iteration_helpers.html">
<link rel="import" href="/base/statistics.html">
<link rel="import" href="/base/ui/dom_helpers.html">
<link rel="import" href="/base/ui/pie_chart.html">
<link rel="import" href="/base/ui/sortable_table.html">
<link rel="import" href="/base/ui/sunburst_chart.html">

<template id="x-sample-summary-panel-template">
  <style>
    .x-sample-summary-panel {
      display: block;
      overflow: auto;
      padding: 5px;
    }
    .x-sample-summary-panel > x-toolbar {
      display: block;
      border-bottom: 1px solid black;
    }

    .x-sample-summary-panel > x-left-panel {
      position: relative;
      width: 610px;
      left: 0;
      top: 0;
      height: 610px;
      padding: 5px;
    }

    .x-sample-summary-panel > x-left-panel > result-area {
      display: block;
      width: 610px;
      position: absolute;
      left: 0;
      top: 0;
      height: 610px;
    }

    .x-sample-summary-panel > x-left-panel > x-explanation {
      display: block;
      position: absolute;
      top: 300px;
      left: 250px;
      width: 100px;
      height: 100px;
      text-align: center;
      vertical-align:middle;
      color: #666;
      font-size: 12px;
    }

    .x-sample-summary-panel > x-right-panel {
      display: block;
      min-height: 610px;
      margin-left: 610px;
      padding: 5px;
    }

    .x-sample-summary-panel > x-right-panel td {
      color: #fff;
      padding: 1px 5px;
      font-size: 1.0em;
      white-space: nowrap;
    }

    .x-sample-summary-panel > x-right-panel > x-sequence {
      display: block;
      overflow: auto;
      width: 600px;
      height: 400px;
      font-size: 14px;
      margin: 10px;
    }

    .x-sample-summary-panel > x-right-panel > x-sequence table {
      min-width: 600px;
    }

    .x-sample-summary-panel > x-right-panel > x-callees {
      display: block;
      position: relative;
      width: 600px;
      height: auto;
      overflow: auto;
      font-size: 14px;
      margin: 10px;
    }

    .x-sample-summary-panel > x-right-panel > x-callees .x-col-numeric {
      width: 30px;
    }

    .x-sample-summary-panel > x-right-panel > x-callees .x-td-numeric {
      text-align: right;
    }

    .x-sample-summary-panel > x-right-panel > x-callees table {
      min-width: 600px;
      max-width: 600px;
    }

    .x-sample-summary-panel > x-right-panel > x-callees {
      display: block;
      overflow: auto;
      height: 300px;
    }

  </style>

  <x-toolbar></x-toolbar>
  <x-left-panel>
    <result-area></result-area>
    <x-explanation></x-explanation>
  </x-left-panel>
  <x-right-panel>
    <x-sequence></x-sequence>
    <x-callees></x-callees>
  </x-right-panel>
</template>

<script>
'use strict';

tr.exportTo('tr.e.analysis', function() {
  var THIS_DOC = document.currentScript.ownerDocument;

  var RequestSelectionChangeEvent = tr.c.RequestSelectionChangeEvent;
  var getColorOfKey = tr.b.ui.getColorOfKey;

  /**
    * @constructor
    */
  var CallTreeNode = function(name, category) {
    this.parent = undefined;
    this.name = name;
    this.category = category;
    this.selfTime = 0.0;
    this.children = [];

    // Defined only for leaf nodes, leaf_node_id corresponds to
    // the id of the leaf stack frame.
    this.leaf_node_id = undefined;
  };

  CallTreeNode.prototype = {
    addChild: function(node) {
      this.children.push(node);
      node.parent = this;
    }
  };

  /**
   * @constructor
   */
  var Thread = function(thread) {
    this.thread = thread;
    this.rootNode = new CallTreeNode('root', 'root');
    this.rootCategories = {};
    this.sfToNode = {};
    this.sfToNode['__root'] = self.rootNode;
  };

  Thread.prototype = {
    getCallTreeNode: function(stackFrame) {
      if (stackFrame.id in this.sfToNode)
        return this.sfToNode[stackFrame.id];

      // Create & save the node.
      var newNode = new CallTreeNode(stackFrame.title, stackFrame.category);
      this.sfToNode[stackFrame.id] = newNode;

      // Add node to parent tree node.
      if (stackFrame.parentFrame) {
        var parentNode = this.getCallTreeNode(stackFrame.parentFrame);

        parentNode.addChild(newNode);
      } else {
        // Creating a root category node for each category helps group samples
        // that may be missing call stacks.
        var rootCategory = this.rootCategories[stackFrame.category];
        if (!rootCategory) {
          rootCategory =
              new CallTreeNode(stackFrame.category, stackFrame.category);
          this.rootNode.addChild(rootCategory);
          this.rootCategories[stackFrame.category] = rootCategory;
        }
        rootCategory.addChild(newNode);
      }
      return newNode;
    },

    addSample: function(sample) {
      var leaf_node = this.getCallTreeNode(sample.leafStackFrame);
      leaf_node.leaf_node_id = sample.leafStackFrame.id;
      leaf_node.selfTime += sample.weight;
    }
  };

  function genCallTree(node, isRoot) {
    var ret = {
      category: node.category,
      name: node.name,
      leaf_node_id: node.leaf_node_id
    };

    if (isRoot || node.children.length > 0) {
      ret.children = [];
      for (var c = 0; c < node.children.length; c++)
        ret.children.push(genCallTree(node.children[c], false));
      if (node.selfTime > 0.0) {
        // say, caller (r) calls callee (e) which calls callee2 (2)
        // and following are the samples
        // r r r r r r r
        //   e e e
        //   2 2 2
        // In this case, r has a non-zero self time (4 samples to be precise)
        // The <self> node makes the representation resemble the following
        // where s denotes the selftime.
        // r r r r r r r
        // s e e e s s s
        //   2 2 2
        //
        // Among the obvious visualization benefit, this also creates the
        // invariance that a node can not simultaneously have samples and
        // children.
        ret.children.push({
          name: '<self>',
          category: ret.category,
          size: node.selfTime,
          leaf_node_id: node.leaf_node_id
        });
        delete ret.leaf_node_id;  // ret is not a leaf node anymore.
      }
    }
    else {
      ret.size = node.selfTime;
    }
    if (isRoot)
      return ret.children;
    return ret;
  }

  function getSampleTypes(selection) {
    var sampleDict = {};
    var samples = selection.getEventsOrganizedByBaseType().sample;
    for (var i = 0; i < samples.length; i++) {
      sampleDict[samples[i].title] = null;
    }
    return Object.keys(sampleDict);
  }

  // Create sunburst data from the selection.
  function createSunburstData(selection, sampleType) {
    var threads = {};
    function getOrCreateThread(thread) {
      var ret = undefined;
      if (thread.tid in threads) {
        ret = threads[thread.tid];
      } else {
        ret = new Thread(thread);
        threads[thread.tid] = ret;
      }
      return ret;
    }

    // Process samples.
    var samples = selection.getEventsOrganizedByBaseType().sample;
    for (var i = 0; i < samples.length; i++) {
      var sample = samples[i];
      if (sample.title == sampleType)
        getOrCreateThread(sample.thread).addSample(sample);
    }

    // Generate sunburst data.
    var sunburstData = {
      name: '<All Threads>',
      category: 'root',
      children: []
    };
    for (var t in threads) {
      if (!threads.hasOwnProperty(t)) continue;
      var thread = threads[t];
      var threadData = {
        name: 'Thread ' + thread.thread.tid + ': ' + thread.thread.name,
        category: 'Thread',
        children: genCallTree(thread.rootNode, true)
      };
      sunburstData.children.push(threadData);
    }
    return sunburstData;
  }

  /**
   * @constructor
   */
  var SamplingSummaryPanel =
      tr.b.ui.define('x-sample-summary-panel');
  SamplingSummaryPanel.textLabel = 'Sampling Summary';
  SamplingSummaryPanel.supportsModel = function(m) {
    if (m == undefined) {
      return {
        supported: false,
        reason: 'Unknown tracing model'
      };
    }

    if (m.samples.length == 0) {
      return {
        supported: false,
        reason: 'No sampling data in trace'
      };
    }

    return {
      supported: true
    };
  };

  // Return a dict with keys as stack-frame ids
  // and values as selection objects which contain all the
  // samples whose leaf stack-frame id matches the key.
  function divideSamplesBasedOnLeafStackFrame(selection) {
    var stackFrameIdToSamples = {};
    for (var i = 0; i < selection.length; ++i) {
      var sample = selection[i];
      var id = sample.leafStackFrame.id;
      if (!stackFrameIdToSamples[id])
        stackFrameIdToSamples[id] = new tr.c.Selection();
      stackFrameIdToSamples[id].push(sample);
    }
    return stackFrameIdToSamples;
  }

  SamplingSummaryPanel.prototype = {
    __proto__: HTMLUnknownElement.prototype,

    decorate: function() {
      this.classList.add('x-sample-summary-panel');
      this.appendChild(tr.b.instantiateTemplate(
          '#x-sample-summary-panel-template', THIS_DOC));

      this.sampleType_ = undefined;
      this.sampleTypeSelector_ = undefined;
      this.chart_ = undefined;
      this.selection_ = undefined;
    },

    get selection() {
      return this.selection_;
    },

    set selection(selection) {
      this.selection_ = selection;
      this.stackFrameIdToSamples_ = divideSamplesBasedOnLeafStackFrame(
          selection);
      this.updateContents_();
    },

    get sampleType() {
      return this.sampleType_;
    },

    set sampleType(type) {
      this.sampleType_ = type;
      if (this.sampleTypeSelector_)
        this.sampleTypeSelector_.selectedValue = type;
      this.updateResultArea_();
    },

    updateCallees_: function(d) {
      // Update callee table.
      var that = this;
      var table = document.createElement('table');

      // Add column styles.
      var col0 = document.createElement('col');
      var col1 = document.createElement('col');
      col0.className += 'x-col-numeric';
      col1.className += 'x-col-numeric';
      table.appendChild(col0);
      table.appendChild(col1);

      // Add headers.
      var thead = table.createTHead();
      var headerRow = thead.insertRow(0);
      headerRow.style.backgroundColor = '#888';
      headerRow.insertCell(0).appendChild(document.createTextNode('Samples'));
      headerRow.insertCell(1).appendChild(document.createTextNode('Percent'));
      headerRow.insertCell(2).appendChild(document.createTextNode('Symbol'));

      // Add body.
      var tbody = table.createTBody();
      if (d.children) {
        for (var i = 0; i < d.children.length; i++) {
          var c = d.children[i];
          var row = tbody.insertRow(i);
          var bgColor = getColorOfKey(c.category);
          if (bgColor == undefined)
            bgColor = '#444444';
          row.style.backgroundColor = bgColor;
          var cell0 = row.insertCell(0);
          var cell1 = row.insertCell(1);
          var cell2 = row.insertCell(2);
          cell0.className += 'x-td-numeric';
          cell1.className += 'x-td-numeric';
          cell0.appendChild(document.createTextNode(c.value.toString()));
          cell1.appendChild(document.createTextNode(
              (100 * c.value / d.value).toFixed(2) + '%'));
          cell2.appendChild(document.createTextNode(c.name));
        }
      }

      // Make it sortable.
      tr.b.ui.SortableTable.decorate(table);

      var calleeArea = that.querySelector('x-callees');
      calleeArea.textContent = '';
      calleeArea.appendChild(table);
    },

    updateHighlight_: function(d) {
      var that = this;

      // Update explanation.
      var percent = 100.0;
      if (that.chart_.selectedNode != null)
        percent = 100.0 * d.value / that.chart_.selectedNode.value;
      that.querySelector('x-explanation').innerHTML =
          d.value + '<br>' + percent.toFixed(2) + '%';

      // Update call stack table.
      var table = document.createElement('table');
      var thead = table.createTHead();
      var tbody = table.createTBody();
      var headerRow = thead.insertRow(0);
      headerRow.style.backgroundColor = '#888';
      headerRow.insertCell(0).appendChild(
          document.createTextNode('Call Stack'));

      var callStack = [];
      var frame = d;
      while (frame && frame.id) {
        callStack.push(frame);
        frame = frame.parent;
      }

      for (var i = 0; i < callStack.length; i++) {
        var row = tbody.insertRow(i);
        var bgColor = getColorOfKey(callStack[i].category);
        if (bgColor == undefined)
          bgColor = '#444444';
        row.style.backgroundColor = bgColor;
        if (i == 0)
          row.style.fontWeight = 'bold';
        row.insertCell(0).appendChild(
            document.createTextNode(callStack[i].name));
      }

      var sequenceArea = that.querySelector('x-sequence');
      sequenceArea.textContent = '';
      sequenceArea.appendChild(table);
    },

    getSamplesFromNode_: function(node) {
      // A node has samples associated with it, if it's a leaf node.
      var selection = new tr.c.Selection();
      if (node.leaf_node_id !== undefined) {
        selection.addSelection(this.stackFrameIdToSamples_[node.leaf_node_id]);
      }
      else if (node.children === undefined ||
               node.children.length === 0) {
        throw new Error('A node should either have samples, or children');
      }
      else {
        for (var i = 0; i < node.children.length; ++i)
          selection.addSelection(this.getSamplesFromNode_(node.children[i]));
      }
      return selection;
    },

    updateResultArea_: function() {
      if (this.selection_ === undefined)
        return;

      var resultArea = this.querySelector('result-area');
      this.chart_ = undefined;
      resultArea.textContent = '';

      var sunburstData =
          createSunburstData(this.selection_, this.sampleType_);
      this.chart_ = new tr.b.ui.SunburstChart();
      this.chart_.width = 600;
      this.chart_.height = 600;
      this.chart_.chartTitle = 'Sampling Summary';

      this.chart_.addEventListener('node-selected', (function(e) {
        this.updateCallees_(e.node);
      }).bind(this));

      this.chart_.addEventListener('node-clicked', (function(e) {
        var event = new RequestSelectionChangeEvent();
        var depth = e.node.depth;
        if (e.node.name === '<self>')
          depth--;
        event.selection = this.getSamplesFromNode_(e.node);
        event.selection.sunburst_zoom_level = depth;
        this.dispatchEvent(event);
      }).bind(this));

      this.chart_.addEventListener('node-highlighted', (function(e) {
        this.updateHighlight_(e.node);
      }).bind(this));

      this.chart_.data = {
        nodes: sunburstData
      };

      resultArea.appendChild(this.chart_);
      this.chart_.setSize(this.chart_.getMinSize());

      if (this.selection_.sunburst_zoom_level !== undefined) {
        this.chart_.zoomToDepth(this.selection_.sunburst_zoom_level);
      }
    },

    updateContents_: function() {
      if (this.selection_ === undefined || this.selection_.length == 0)
        return;

      // Get available sample types in range.
      var sampleTypes = getSampleTypes(this.selection_);
      if (sampleTypes.indexOf(this.sampleType_) == -1)
        this.sampleType_ = sampleTypes[0];

      // Create sample type dropdown.
      var sampleTypeOptions = [];
      for (var i = 0; i < sampleTypes.length; i++)
        sampleTypeOptions.push({label: sampleTypes[i], value: sampleTypes[i]});

      var toolbarEl = this.querySelector('x-toolbar');
      this.sampleTypeSelector_ = tr.b.ui.createSelector(
          this,
          'sampleType',
          'samplingSummaryPanel.sampleType',
          this.sampleType_,
          sampleTypeOptions);
      toolbarEl.textContent = 'Sample Type: ';
      toolbarEl.appendChild(this.sampleTypeSelector_);
    }
  };

  return {
    SamplingSummaryPanel: SamplingSummaryPanel,
    createSunburstData: createSunburstData
  };
});
</script>
