<!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/event_presenter.html">
<link rel="import" href="/model/proxy_selectable_item.html">
<link rel="import" href="/core/tracks/heading_track.html">
<link rel="import" href="/base/ui/color_scheme.html">
<link rel="import" href="/base/sorted_array_utils.html">
<link rel="import" href="/base/ui.html">
<style>
.letter-dot-track {
  height: 18px;
}
</style>

<script>
'use strict';

tr.exportTo('tr.c.tracks', function() {
  var EventPresenter = tr.c.EventPresenter;
  var SelectionState = tr.model.SelectionState;

  /**
   * A track that displays an array of dots with filled letters inside them.
   * @constructor
   * @extends {HeadingTrack}
   */
  var LetterDotTrack = tr.b.ui.define(
      'letter-dot-track', tr.c.tracks.HeadingTrack);

  LetterDotTrack.prototype = {
    __proto__: tr.c.tracks.HeadingTrack.prototype,

    decorate: function(viewport) {
      tr.c.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
      this.classList.add('letter-dot-track');
      this.items_ = undefined;
    },

    get items() {
      return this.items_;
    },

    set items(items) {
      this.items_ = items;
      this.invalidateDrawingContainer();
    },

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

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

    get dumpRadiusView() {
      return 7 * (window.devicePixelRatio || 1);
    },

    draw: function(type, viewLWorld, viewRWorld) {
      if (this.items_ === undefined)
        return;
      switch (type) {
        case tr.c.tracks.DrawType.GENERAL_EVENT:
          this.drawLetterDots_(viewLWorld, viewRWorld);
          break;
      }
    },

    drawLetterDots_: function(viewLWorld, viewRWorld) {
      var ctx = this.context();
      var pixelRatio = window.devicePixelRatio || 1;

      var bounds = this.getBoundingClientRect();
      var height = bounds.height * pixelRatio;
      var halfHeight = height * 0.5;
      var twoPi = Math.PI * 2;
      var palette = tr.b.ui.getColorPalette();
      var highlightIdBoost = tr.b.ui.paletteProperties.highlightIdBoost;

      // Culling parameters.
      var dt = this.viewport.currentDisplayTransform;
      var dumpRadiusView = this.dumpRadiusView;
      var itemRadiusWorld = dt.xViewVectorToWorld(height);

      // Draw the memory dumps.
      var items = this.items_;
      var loI = tr.b.findLowIndexInSortedArray(
          items,
          function(item) { return item.start; },
          viewLWorld);

      var oldFont = ctx.font;
      ctx.font = '400 ' + Math.floor(9 * pixelRatio) + 'px Arial';
      ctx.strokeStyle = 'rgb(0,0,0)';
      ctx.textBaseline = 'middle';
      ctx.textAlign = 'center';

      var drawItems = function(selected) {
        for (var i = loI; i < items.length; ++i) {
          var item = items[i];
          var x = item.start;
          if (x - itemRadiusWorld > viewRWorld)
            break;
          if (item.selected !== selected)
            continue;
          var xView = dt.xWorldToView(x);

          ctx.fillStyle = EventPresenter.getSelectableItemColor(item);
          ctx.beginPath();
          ctx.arc(xView, halfHeight, dumpRadiusView + 0.5, 0, twoPi);
          ctx.fill();
          if (item.selected) {
            ctx.lineWidth = 3;
            ctx.strokeStyle = 'rgb(100,100,0)';
            ctx.stroke();

            ctx.beginPath();
            ctx.arc(xView, halfHeight, dumpRadiusView, 0, twoPi);
            ctx.lineWidth = 1.5;
            ctx.strokeStyle = 'rgb(255,255,0)';
            ctx.stroke();
          } else {
            ctx.lineWidth = 1;
            ctx.strokeStyle = 'rgb(0,0,0)';
            ctx.stroke();
          }

          ctx.fillStyle = 'rgb(255, 255, 255)';
          ctx.fillText(item.dotLetter, xView, halfHeight);
        }
      };

      // Draw unselected items first to make sure they don't occlude selected
      // items.
      drawItems(false);
      drawItems(true);

      ctx.lineWidth = 1;
      ctx.font = oldFont;
    },

    addEventsToTrackMap: function(eventToTrackMap) {
      if (this.items_ === undefined)
        return;

      this.items_.forEach(function(item) {
        item.addToTrackMap(eventToTrackMap, this);
      }, this);
    },

    addIntersectingEventsInRangeToSelectionInWorldSpace: function(
        loWX, hiWX, viewPixWidthWorld, selection) {
      if (this.items_ === undefined)
        return;

      var itemRadiusWorld = viewPixWidthWorld * this.dumpRadiusView;
      tr.b.iterateOverIntersectingIntervals(
          this.items_,
          function(x) { return x.start - itemRadiusWorld; },
          function(x) { return 2 * itemRadiusWorld; },
          loWX, hiWX,
          function(item) {
            item.addToSelection(selection);
          }.bind(this));
    },

    /**
     * Add the item to the left or right of the provided event, if any, to the
     * selection.
     * @param {event} The current event item.
     * @param {Number} offset Number of slices 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
     */
    addEventNearToProvidedEventToSelection: function(event, offset, selection) {
      if (this.items_ === undefined)
        return;

      var items = this.items_;
      var index = tr.b.findFirstIndexInArray(items, function(item) {
        return item.modelItem === event;
      });
      if (index === -1)
        return false;

      var newIndex = index + offset;
      if (newIndex >= 0 && newIndex < items.length) {
        items[newIndex].addToSelection(selection);
        return true;
      }
      return false;
    },

    addAllEventsMatchingFilterToSelection: function(filter, selection) {
    },

    addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
                                         selection) {
      if (this.items_ === undefined)
        return;

      var item = tr.b.findClosestElementInSortedArray(
          this.items_,
          function(x) { return x.start; },
          worldX,
          worldMaxDist);

      if (!item)
        return;

      item.addToSelection(selection);
    }
  };

  /**
   * A filled dot with a letter inside it.
   *
   * @constructor
   * @extends {ProxySelectableItem}
   */
  function LetterDot(modelItem, dotLetter, colorId, start) {
    tr.model.ProxySelectableItem.call(this, modelItem);
    this.dotLetter = dotLetter;
    this.colorId = colorId;
    this.start = start;
  };

  LetterDot.prototype = {
    __proto__: tr.model.ProxySelectableItem.prototype
  };

  return {
    LetterDotTrack: LetterDotTrack,
    LetterDot: LetterDot
  };
});
</script>
