<!DOCTYPE html>
<!--
Copyright (c) 2015 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="/core/analysis/analysis_link.html">
<link rel="import" href="/core/analysis/flow_classifier.html">
<link rel="import" href="/core/selection.html">
<link rel="import" href="/base/ui/table.html">
<link rel="import" href="/base/ui/dom_helpers.html">

<polymer-element name="tr-c-a-related-events">
  <template>
    <style>
    :host {
      display: flex;
      flex-direction: column;
    }
    #table {
      flex: 1 1 auto;
      align-self: stretch;
    }
    </style>
    <tr-b-ui-table id="table"></tr-b-ui-table>
  </template>

  <script>
  'use strict';

  Polymer({
    ready: function() {
      this.eventGroups_ = [];

      this.$.table.tableColumns = [
        {
          title: 'Event(s)',
          value: function(row) { return row.type; },
          width: '150px'
        },
        {
          title: 'Link',
          width: '100%',
          value: function(row) {
            var linkEl = document.createElement('tr-c-a-analysis-link');
            if (row.name)
              linkEl.setSelectionAndContent(row.selection, row.name);
            else
              linkEl.selection = row.selection;
            return linkEl;
          }
        }
      ];
    },

    hasRelatedEvents: function() {
      return (this.eventGroups_ && this.eventGroups_.length > 0);
    },

    addRelatedEvents: function(selection) {
      this.addConnectedFlows_(selection);
      this.addConnectedEvents_(selection);
      this.updateContents_();
    },

    addConnectedFlows_: function(selection) {
      var classifier = new tr.c.analysis.FlowClassifier();
      selection.forEach(function(slice) {
        if (slice.inFlowEvents) {
          slice.inFlowEvents.forEach(function(flow) {
            classifier.addInFlow(flow);
          });
        }
        if (slice.outFlowEvents) {
          slice.outFlowEvents.forEach(function(flow) {
            classifier.addOutFlow(flow);
          });
        }
      });
      if (!classifier.hasEvents())
        return;

      var addToEventGroups = function(type, flowEvent) {
        this.eventGroups_.push({
          type: type,
          selection: new tr.c.Selection(flowEvent),
          name: flowEvent.title
        });
      };

      classifier.inFlowEvents.forEach(
          addToEventGroups.bind(this, 'Incoming flow'));
      classifier.outFlowEvents.forEach(
          addToEventGroups.bind(this, 'Outgoing flow'));
      classifier.internalFlowEvents.forEach(
          addToEventGroups.bind(this, 'Internal flow'));
    },

    addConnectedEvents_: function(selection) {
      // Preceding and following events are only well-defined for single
      // selections.
      if (selection.length === 1)
        this.addConnectedEventsForSlice_(selection[0]);
      else
        this.addConnectedEventsForSelection_(selection);
    },

    addConnectedEventsForSlice_: function(slice) {
      var precedingEventsSelection = undefined;
      var followingEventsSelection = undefined;
      if (slice.inFlowEvents && slice.inFlowEvents.length !== 0) {
        precedingEventsSelection = new tr.c.Selection();
        this.recursivelyAddConnectedEvents_(precedingEventsSelection, {}, slice,
            function(event) { return event.inFlowEvents; });
        this.eventGroups_.push({
          type: 'Preceding events',
          selection: precedingEventsSelection
        });
      }
      if (slice.outFlowEvents && slice.outFlowEvents.length !== 0) {
        followingEventsSelection = new tr.c.Selection();
        this.recursivelyAddConnectedEvents_(followingEventsSelection, {}, slice,
            function(event) { return event.outFlowEvents; });
        this.eventGroups_.push({
          type: 'Following events',
          selection: followingEventsSelection
        });
      }
      if (precedingEventsSelection && followingEventsSelection) {
        var allEventsSelection = new tr.c.Selection();
        for (var i = 0; i < precedingEventsSelection.length; ++i)
          allEventsSelection.push(precedingEventsSelection[i]);
        // Do not add the first event of followingEventsSelection since it's
        // the slice too.
        for (var i = 1; i < followingEventsSelection.length; ++i)
          allEventsSelection.push(followingEventsSelection[i]);
        this.eventGroups_.push({
          type: 'All connected events',
          selection: allEventsSelection
        });
      }
    },

    addConnectedEventsForSelection_: function(selection) {
      var eventIds = {};
      var allEventsSelection = new tr.c.Selection();
      selection.forEach(function(slice) {
        this.recursivelyAddConnectedEvents_(allEventsSelection, eventIds, slice,
            function(event) {
              var flows = [];
              if (event.inFlowEvents)
                flows = flows.concat(event.inFlowEvents);
              if (event.outFlowEvents)
                flows = flows.concat(event.outFlowEvents);
              return flows;
            });
      }.bind(this));
      // Add related events if it contains more than the original selection.
      if (allEventsSelection.length > selection.length) {
        this.eventGroups_.push({
          type: 'All connected events',
          selection: allEventsSelection
        });
      }
    },

    updateContents_: function() {
      var table = this.$.table;
      if (this.eventGroups_ === undefined)
        table.tableRows = [];
      else
        table.tableRows = this.eventGroups_.slice();
      table.rebuild();
    },

    recursivelyAddConnectedEvents_: function(selection, eventIds, event,
                                             getFlows) {
      if (!event || eventIds[event.guid])
        return;
      eventIds[event.guid] = true;
      selection.push(event);
      var flowEvents = getFlows(event);
      if (!flowEvents)
        return;
      for (var i = 0; i < flowEvents.length; ++i) {
        selection.push(flowEvents[i]);
        this.recursivelyAddConnectedEvents_(selection, eventIds,
            flowEvents[i].startSlice, getFlows);
        this.recursivelyAddConnectedEvents_(selection, eventIds,
            flowEvents[i].endSlice, getFlows);
      }
    }
  });
  </script>
</polymer-element>
