<!DOCTYPE html>
<!--
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.
-->

<link rel="import" href="/base/events.html">
<link rel="import" href="/base/guid.html">
<link rel="import" href="/base/range.html">
<link rel="import" href="/core/trace_model/trace_model.html">

<script>
'use strict';

/**
 * @fileoverview Code for the viewport.
 */
tv.exportTo('tv.c', function() {

  var EventRegistry = tv.c.trace_model.EventRegistry;

  var RequestSelectionChangeEvent = tv.b.Event.bind(
      undefined, 'requestSelectionChange', true, false);

  /**
   * Represents a selection within a  and its associated set of tracks.
   * @constructor
   */
  function Selection(opt_events) {
    // sunburst_zoom_level is used by sunburst chart to remember
    // zoom level across selection changes.
    // TODO(gholap): get rid of this eventually when
    //               selections support frames.
    this.sunburst_zoom_level = undefined;

    this.bounds_dirty_ = true;
    this.bounds_ = new tv.b.Range();
    this.length_ = 0;
    this.guid_ = tv.b.GUID.allocate();
    this.pushed_guids_ = {};

    if (opt_events) {
      for (var i = 0; i < opt_events.length; i++)
        this.push(opt_events[i]);
    }
  }
  Selection.prototype = {
    __proto__: Object.prototype,

    get bounds() {
      if (this.bounds_dirty_) {
        this.bounds_.reset();
        for (var i = 0; i < this.length_; i++)
          this[i].addBoundsToRange(this.bounds_);
        this.bounds_dirty_ = false;
      }
      return this.bounds_;
    },

    get duration() {
      if (this.bounds_.isEmpty)
        return 0;
      return this.bounds_.max - this.bounds_.min;
    },

    get length() {
      return this.length_;
    },

    get guid() {
      return this.guid_;
    },

    clear: function() {
      for (var i = 0; i < this.length_; ++i)
        delete this[i];
      this.length_ = 0;
      this.bounds_dirty_ = true;
    },

    // push pushes only unique events.
    // If an event has been already pushed, do nothing.
    push: function(event) {
      if (event.guid == undefined)
        throw new Error('Event must have a GUID');

      if (this.pushed_guids_[event.guid])
        return event;

      this.pushed_guids_[event.guid] = true;
      this[this.length_++] = event;
      this.bounds_dirty_ = true;
      return event;
    },

    addSelection: function(selection) {
      for (var i = 0; i < selection.length; i++)
        this.push(selection[i]);
    },

    subSelection: function(index, count) {
      count = count || 1;

      var selection = new Selection();
      selection.bounds_dirty_ = true;
      if (index < 0 || index + count > this.length_)
        throw new Error('Index out of bounds');

      for (var i = index; i < index + count; i++)
        selection.push(this[i]);

      return selection;
    },

    getEventsOrganizedByBaseType: function(opt_pruneEmpty) {
      var events = {};
      var allTypeInfos = EventRegistry.getAllRegisteredTypeInfos();
      allTypeInfos.forEach(function(eventTypeInfo) {
        events[eventTypeInfo.metadata.name] = new Selection();
        if (this.sunburst_zoom_level !== undefined)
          events[eventTypeInfo.metadata.name].sunburst_zoom_level =
              this.sunburst_zoom_level;
      }, this);

      this.forEach(function(event, i) {
        var maxEventIndex = -1;
        var maxEventTypeInfo = undefined;
        allTypeInfos.forEach(function(eventTypeInfo, eventIndex) {
          if (!(event instanceof eventTypeInfo.constructor))
            return;
          if (eventIndex > maxEventIndex) {
            maxEventIndex = eventIndex;
            maxEventTypeInfo = eventTypeInfo;
          }
        });
        if (maxEventIndex == -1)
          throw new Error('Unrecgonized event type');
        events[maxEventTypeInfo.metadata.name].push(event);
      });
      if (opt_pruneEmpty) {
        var prunedEvents = {};
        for (var eventType in events) {
          if (events[eventType].length > 0)
            prunedEvents[eventType] = events[eventType];
        }
        return prunedEvents;
      } else {
        return events;
      }
    },

    enumEventsOfType: function(type, func) {
      for (var i = 0; i < this.length_; i++)
        if (this[i] instanceof type)
          func(this[i]);
    },

    /**
     * Helper for selection previous or next.
     * @param {boolean} offset If positive, select one forward (next).
     *   Else, select previous.
     *
     * @param {TimelineViewport} viewport The viewport to use to determine what
     * is near to the current selection.
     *
     * @return {boolean} true if current selection changed.
     */
    getShiftedSelection: function(viewport, offset) {
      var newSelection = new Selection();
      for (var i = 0; i < this.length_; i++) {
        var event = this[i];

        var addEventToNewSelection = function(event) {
        };

        // If this is a flow event, and we have a next/prev item in the chain
        // then we use that as the item to move too. Otherwise, we let the
        // normal movement for a slice kick in and use that.
        if (event instanceof tv.c.trace_model.FlowEvent) {
          if ((offset > 0) && event.nextFlowEvent) {
            newSelection.push(event.nextFlowEvent);
            continue;
          } else if ((offset < 0) && event.previousFlowEvent) {
            newSelection.push(event.previousFlowEvent);
            continue;
          }
        }

        var track = viewport.trackForEvent(event);
        track.addItemNearToProvidedEventToSelection(
            event, offset, newSelection);
      }

      if (newSelection.length == 0)
        return undefined;
      return newSelection;
    },

    forEach: function(fn, opt_this) {
      for (var i = 0; i < this.length; i++)
        fn.call(opt_this, this[i], i);
    },

    map: function(fn, opt_this) {
      var res = [];
      for (var i = 0; i < this.length; i++)
        res.push(fn.call(opt_this, this[i], i));
      return res;
    },

    every: function(fn, opt_this) {
      for (var i = 0; i < this.length; i++)
        if (!fn.call(opt_this, this[i], i))
          return false;
      return true;
    },

    some: function(fn, opt_this) {
      for (var i = 0; i < this.length; i++)
        if (fn.call(opt_this, this[i], i))
          return true;
      return false;
    }
  };

  return {
    Selection: Selection,
    RequestSelectionChangeEvent: RequestSelectionChangeEvent
  };
});
</script>
