<!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="/base/iteration_helpers.html">
<link rel="import" href="/model/model.html">

<script>
'use strict';

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

  var EventRegistry = tr.model.EventRegistry;

  var RequestSelectionChangeEvent = tr.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 tr.b.Range();
    this.length_ = 0;
    this.guid_ = tr.b.GUID.allocate();
    this.pushed_guids_ = {};

    if (opt_events) {
      if (opt_events instanceof Array) {
        for (var i = 0; i < opt_events.length; i++)
          this.push(opt_events[i]);
      } else {
        this.push(opt_events);
      }
    }
  }
  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.contains(event))
        return event;

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

    contains: function(event) {
      return this.pushed_guids_[event.guid];
    },

    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;
    },

    equals: function(that) {
      if (this.length !== that.length)
        return false;
      for (var i = 0; i < this.length; i++) {
        var event = this[i];
        if (that.pushed_guids_[event.guid] === undefined)
          return false;
      }
      return true;
    },

    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) {
          console.log(event);
          throw new Error('Unrecognized 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;
      }
    },

    getEventsOrganizedByTitle: function() {
      var eventsByTitle = {};
      for (var i = 0; i < this.length; i++) {
        var event = this[i];
        if (event.title === undefined)
          throw new Error('An event didn\'t have a title!');
        if (eventsByTitle[event.title] == undefined) {
          eventsByTitle[event.title] = [];
        }
        eventsByTitle[event.title].push(event);
      }
      return eventsByTitle;
    },

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

    get userFriendlyName() {
      if (this.length === 0) {
        throw new Error('Empty selection');
      }

      var eventsByBaseType = this.getEventsOrganizedByBaseType(true);
      var eventTypeName = tr.b.dictionaryKeys(eventsByBaseType)[0];

      if (this.length === 1) {
        var tmp = EventRegistry.getUserFriendlySingularName(eventTypeName);
        return this[0].userFriendlyName;
      }

      var numEventTypes = tr.b.dictionaryLength(eventsByBaseType);
      if (numEventTypes !== 1) {
        return this.length + ' events of various types';
      }

      var tmp = EventRegistry.getUserFriendlyPluralName(eventTypeName);
      return this.length + ' ' + tmp;
    },

    /**
     * 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];

        // If this is a flow event, then move to its slice based on the
        // offset direction.
        if (event instanceof tr.model.FlowEvent) {
          if (offset > 0) {
            newSelection.push(event.endSlice);
          } else if (offset < 0) {
            newSelection.push(event.startSlice);
          } else {
            /* Do nothing. Zero offsets don't do anything. */
          }
          continue;
        }

        var track = viewport.trackForEvent(event);
        track.addEventNearToProvidedEventToSelection(
            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>
