<!DOCTYPE html>
<!--
Copyright (c) 2013 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="/tracing/ui/tracks/process_memory_dump_track.html">
<link rel="import" href="/tracing/ui/tracks/process_track_base.html">
<link rel="import" href="/tracing/ui/base/draw_helpers.html">

<script>
'use strict';

tr.exportTo('tr.ui.tracks', function() {
  var ProcessTrackBase = tr.ui.tracks.ProcessTrackBase;

  /**
   * @constructor
   */
  var ProcessTrack = tr.ui.b.define('process-track', ProcessTrackBase);

  ProcessTrack.prototype = {
    __proto__: ProcessTrackBase.prototype,

    decorate: function(viewport) {
      tr.ui.tracks.ProcessTrackBase.prototype.decorate.call(this, viewport);
    },

    drawTrack: function(type) {
      switch (type) {
        case tr.ui.tracks.DrawType.INSTANT_EVENT:
          if (!this.processBase.instantEvents ||
              this.processBase.instantEvents.length === 0)
            break;

          var ctx = this.context();

          var pixelRatio = window.devicePixelRatio || 1;
          var bounds = this.getBoundingClientRect();
          var canvasBounds = ctx.canvas.getBoundingClientRect();

          ctx.save();
          ctx.translate(0, pixelRatio * (bounds.top - canvasBounds.top));

          var dt = this.viewport.currentDisplayTransform;
          var viewLWorld = dt.xViewToWorld(0);
          var viewRWorld = dt.xViewToWorld(
              bounds.width * pixelRatio);

          tr.ui.b.drawInstantSlicesAsLines(
              ctx,
              this.viewport.currentDisplayTransform,
              viewLWorld,
              viewRWorld,
              bounds.height,
              this.processBase.instantEvents,
              2);

          ctx.restore();

          break;

        case tr.ui.tracks.DrawType.BACKGROUND:
          this.drawBackground_();
          // Don't bother recursing further, Process is the only level that
          // draws backgrounds.
          return;
      }

      tr.ui.tracks.ContainerTrack.prototype.drawTrack.call(this, type);
    },

    drawBackground_: function() {
      var ctx = this.context();
      var canvasBounds = ctx.canvas.getBoundingClientRect();
      var pixelRatio = window.devicePixelRatio || 1;

      var draw = false;
      ctx.fillStyle = '#eee';
      for (var i = 0; i < this.children.length; ++i) {
        if (!(this.children[i] instanceof tr.ui.tracks.Track) ||
            (this.children[i] instanceof tr.ui.tracks.SpacingTrack))
          continue;

        draw = !draw;
        if (!draw)
          continue;

        var bounds = this.children[i].getBoundingClientRect();
        ctx.fillRect(0, pixelRatio * (bounds.top - canvasBounds.top),
            ctx.canvas.width, pixelRatio * bounds.height);
      }
    },

    // Process maps to processBase because we derive from ProcessTrackBase.
    set process(process) {
      this.processBase = process;
    },

    get process() {
      return this.processBase;
    },

    get eventContainer() {
      return this.process;
    },

    addContainersToTrackMap: function(containerToTrackMap) {
      containerToTrackMap.addContainer(this.process, this);
      this.tracks_.forEach(function(track) {
        track.addContainersToTrackMap(containerToTrackMap);
      });
    },

    appendMemoryDumpTrack_: function() {
      var processMemoryDumps = this.process.memoryDumps;
      if (processMemoryDumps.length) {
        var pmdt = new tr.ui.tracks.ProcessMemoryDumpTrack(this.viewport_);
        pmdt.memoryDumps = processMemoryDumps;
        this.appendChild(pmdt);
      }
    },

    addIntersectingEventsInRangeToSelectionInWorldSpace: function(
        loWX, hiWX, viewPixWidthWorld, selection) {
      function onPickHit(instantEvent) {
        selection.push(instantEvent);
      }
      var instantEventWidth = 2 * viewPixWidthWorld;
      tr.b.iterateOverIntersectingIntervals(this.processBase.instantEvents,
          function(x) { return x.start; },
          function(x) { return x.duration + instantEventWidth; },
          loWX, hiWX,
          onPickHit.bind(this));

      tr.ui.tracks.ContainerTrack.prototype.
          addIntersectingEventsInRangeToSelectionInWorldSpace.
          apply(this, arguments);
    },

    addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
                                         selection) {
      this.addClosestInstantEventToSelection(this.processBase.instantEvents,
                                             worldX, worldMaxDist, selection);
      tr.ui.tracks.ContainerTrack.prototype.addClosestEventToSelection.
          apply(this, arguments);
    }
  };

  return {
    ProcessTrack: ProcessTrack
  };
});
</script>

