// Copyright (c) 2012 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.

'use strict';

tvcm.requireStylesheet('tracing.tracks.rect_track');

tvcm.require('tvcm.sorted_array_utils');
tvcm.require('tracing.tracks.heading_track');
tvcm.require('tracing.fast_rect_renderer');
tvcm.require('tracing.draw_helpers');
tvcm.require('tvcm.ui');

tvcm.exportTo('tracing.tracks', function() {

  /**
   * A track that displays an array of Rect objects.
   * @constructor
   * @extends {HeadingTrack}
   */
  var RectTrack = tvcm.ui.define(
      'rect-track', tracing.tracks.HeadingTrack);

  RectTrack.prototype = {

    __proto__: tracing.tracks.HeadingTrack.prototype,

    decorate: function(viewport) {
      tracing.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
      this.classList.add('rect-track');
      this.asyncStyle_ = false;
      this.rects_ = null;
    },

    get asyncStyle() {
      return this.asyncStyle_;
    },

    set asyncStyle(v) {
      this.asyncStyle_ = !!v;
    },

    get rects() {
      return this.rects_;
    },

    set rects(rects) {
      this.rects_ = rects || [];
    },

    get height() {
      return window.getComputedStyle(this).height;
    },

    set height(height) {
      this.style.height = height;
    },

    get hasVisibleContent() {
      return this.rects.length > 0;
    },

    draw: function(type, viewLWorld, viewRWorld) {
      switch (type) {
        case tracing.tracks.DrawType.RECT:
          this.drawRects_(viewLWorld, viewRWorld);
          break;
      }
    },

    drawRects_: function(viewLWorld, viewRWorld) {
      var ctx = this.context();

      ctx.save();
      var bounds = this.getBoundingClientRect();
      tracing.drawRects(
          ctx,
          this.viewport.currentDisplayTransform,
          viewLWorld,
          viewRWorld,
          bounds.height,
          this.rects_,
          this.asyncStyle_);
      ctx.restore();

      if (bounds.height <= 8)
        return;

      tracing.drawLabels(
          ctx,
          this.viewport.currentDisplayTransform,
          viewLWorld,
          viewRWorld,
          this.rects_,
          this.asyncStyle_);
    },

    addEventsToTrackMap: function(eventToTrackMap) {
      if (this.rects_ === undefined || this.rects_ === null)
        return;

      this.rects_.forEach(function(rect) {
        eventToTrackMap.addEvent(rect, this);
      }, this);
    },

    addIntersectingItemsInRangeToSelectionInWorldSpace: function(
        loWX, hiWX, viewPixWidthWorld, selection) {
      function onRect(rect) {
        selection.push(rect);
      }
      tvcm.iterateOverIntersectingIntervals(this.rects_,
          function(x) { return x.start; },
          function(x) { return x.duration; },
          loWX, hiWX,
          onRect);
    },

    /**
     * Find the index for the given rect.
     * @return {index} Index of the given rect, or undefined.
     * @private
     */
    indexOfRect_: function(rect) {
      var index = tvcm.findLowIndexInSortedArray(this.rects_,
          function(x) { return x.start; },
          rect.start);
      while (index < this.rects_.length &&
          rect.start == this.rects_[index].start &&
          rect.colorId != this.rects_[index].colorId) {
        index++;
      }
      return index < this.rects_.length ? index : undefined;
    },

    /**
     * Add the item to the left or right of the provided event, if any, to the
     * selection.
     * @param {rect} The current rect.
     * @param {Number} offset Number of rects away from the event to look.
     * @param {Selection} selection The selection to add an event to,
     * if found.
     * @return {boolean} Whether an event was found.
     * @private
     */
    addItemNearToProvidedEventToSelection: function(event, offset, selection) {
      var index = this.indexOfRect_(event);
      if (index === undefined)
        return false;

      var newIndex = index + offset;
      if (newIndex < 0 || newIndex >= this.rects_.length)
        return false;

      selection.push(this.rects_[newIndex]);
      return true;
    },

    addAllObjectsMatchingFilterToSelection: function(filter, selection) {
      for (var i = 0; i < this.rects_.length; ++i) {
        if (filter.matchSlice(this.rects_[i]))
          selection.push(this.rects_[i]);
      }
    },

    addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
                                         selection) {
      var rect = tvcm.findClosestIntervalInSortedIntervals(
          this.rects_,
          function(x) { return x.start; },
          function(x) { return x.end; },
          worldX,
          worldMaxDist);

      if (rect)
        selection.push(rect);
    }
  };

  return {
    RectTrack: RectTrack
  };
});

@@ -1541,12 +1541,13 @@
 ype.
-RECT
+SLICE
 :%0A  
@@ -1797,20 +1797,21 @@
 ing.draw
-Rect
+Slice
 s(%0A     

Fix slices so they render