<!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="/tracing/base/range_utils.html">
<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
<link rel="import" href="/tracing/importer/proto_expectation.html">

<script>
'use strict';

tr.exportTo('tr.importer', function() {
  var ProtoExpectation = tr.importer.ProtoExpectation;

  var INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES;

  var KEYBOARD_TYPE_NAMES = [
    INPUT_TYPE.CHAR,
    INPUT_TYPE.KEY_DOWN_RAW,
    INPUT_TYPE.KEY_DOWN,
    INPUT_TYPE.KEY_UP
  ];
  var MOUSE_RESPONSE_TYPE_NAMES = [
    INPUT_TYPE.CLICK,
    INPUT_TYPE.CONTEXT_MENU
  ];
  var MOUSE_WHEEL_TYPE_NAMES = [
    INPUT_TYPE.MOUSE_WHEEL
  ];
  var MOUSE_DRAG_TYPE_NAMES = [
    INPUT_TYPE.MOUSE_DOWN,
    INPUT_TYPE.MOUSE_MOVE,
    INPUT_TYPE.MOUSE_UP
  ];
  var TAP_TYPE_NAMES = [
    INPUT_TYPE.TAP,
    INPUT_TYPE.TAP_CANCEL,
    INPUT_TYPE.TAP_DOWN
  ];
  var PINCH_TYPE_NAMES = [
    INPUT_TYPE.PINCH_BEGIN,
    INPUT_TYPE.PINCH_END,
    INPUT_TYPE.PINCH_UPDATE
  ];
  var FLING_TYPE_NAMES = [
    INPUT_TYPE.FLING_CANCEL,
    INPUT_TYPE.FLING_START
  ];
  var TOUCH_TYPE_NAMES = [
    INPUT_TYPE.TOUCH_END,
    INPUT_TYPE.TOUCH_MOVE,
    INPUT_TYPE.TOUCH_START
  ];
  var SCROLL_TYPE_NAMES = [
    INPUT_TYPE.SCROLL_BEGIN,
    INPUT_TYPE.SCROLL_END,
    INPUT_TYPE.SCROLL_UPDATE
  ];
  var ALL_HANDLED_TYPE_NAMES = [].concat(
    KEYBOARD_TYPE_NAMES,
    MOUSE_RESPONSE_TYPE_NAMES,
    MOUSE_WHEEL_TYPE_NAMES,
    MOUSE_DRAG_TYPE_NAMES,
    PINCH_TYPE_NAMES,
    TAP_TYPE_NAMES,
    FLING_TYPE_NAMES,
    TOUCH_TYPE_NAMES,
    SCROLL_TYPE_NAMES
  );

  var RENDERER_FLING_TITLE = 'InputHandlerProxy::HandleGestureFling::started';
  var PLAYBACK_EVENT_TITLE = 'VideoPlayback';

  var CSS_ANIMATION_TITLE = 'Animation';

  /**
   * If there's less than this much time between the end of one event and the
   * start of the next, then they might be merged.
   * There was not enough thought given to this value, so if you have any slight
   * reason to change it, then please do so. It might also be good to split this
   * into multiple values.
   */
  var INPUT_MERGE_THRESHOLD_MS = 200;
  var ANIMATION_MERGE_THRESHOLD_MS = 32;   // 2x 60FPS frames

  /**
   * If two MouseWheel events begin this close together, then they're an
   * Animation, not two responses.
   */
  var MOUSE_WHEEL_THRESHOLD_MS = 40;

  /**
   * If two MouseMoves are more than this far apart, then they're two Responses,
   * not Animation.
   */
  var MOUSE_MOVE_THRESHOLD_MS = 40;

  // Strings used to name IRs.
  var KEYBOARD_IR_NAME = 'Keyboard';
  var MOUSE_IR_NAME = 'Mouse';
  var MOUSEWHEEL_IR_NAME = 'MouseWheel';
  var TAP_IR_NAME = 'Tap';
  var PINCH_IR_NAME = 'Pinch';
  var FLING_IR_NAME = 'Fling';
  var TOUCH_IR_NAME = 'Touch';
  var SCROLL_IR_NAME = 'Scroll';
  var CSS_IR_NAME = 'CSS';
  var WEBGL_IR_NAME = 'WebGL';
  var VIDEO_IR_NAME = 'Video';

  // TODO(benjhayden) Find a better home for this.
  function compareEvents(x, y) {
    if (x.start !== y.start)
      return x.start - y.start;
    if (x.end !== y.end)
      return x.end - y.end;
    if (x.guid && y.guid)
      return x.guid - y.guid;
    return 0;
  }

  function forEventTypesIn(events, typeNames, cb, opt_this) {
    events.forEach(function(event) {
      if (typeNames.indexOf(event.typeName) >= 0) {
        cb.call(opt_this, event);
      }
    });
  }

  function causedFrame(event) {
    return event.associatedEvents.some(
        x => x.title === tr.model.helpers.IMPL_RENDERING_STATS);
  }

  function getSortedFrameEventsByProcess(modelHelper) {
    var frameEventsByPid = {};
    tr.b.iterItems(modelHelper.rendererHelpers, function(pid, rendererHelper) {
      frameEventsByPid[pid] = rendererHelper.getFrameEventsInRange(
          tr.model.helpers.IMPL_FRAMETIME_TYPE, modelHelper.model.bounds);
    });
    return frameEventsByPid;
  }

  function getSortedInputEvents(modelHelper) {
    var inputEvents = [];

    var browserProcess = modelHelper.browserHelper.process;
    var mainThread = browserProcess.findAtMostOneThreadNamed(
        'CrBrowserMain');
    for (var slice of mainThread.asyncSliceGroup.getDescendantEvents()) {
      if (!slice.isTopLevel)
        continue;

      if (!(slice instanceof tr.e.cc.InputLatencyAsyncSlice))
        continue;

      // TODO(beaudoin): This should never happen but it does. Investigate
      // the trace linked at in #1567 and remove that when it's fixed.
      if (isNaN(slice.start) ||
          isNaN(slice.duration) ||
          isNaN(slice.end))
        continue;

      inputEvents.push(slice);
    }

    return inputEvents.sort(compareEvents);
  }

  function findProtoExpectations(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    // This order is not important. Handlers are independent.
    var handlers = [
      handleKeyboardEvents,
      handleMouseResponseEvents,
      handleMouseWheelEvents,
      handleMouseDragEvents,
      handleTapResponseEvents,
      handlePinchEvents,
      handleFlingEvents,
      handleTouchEvents,
      handleScrollEvents,
      handleCSSAnimations,
      handleWebGLAnimations,
      handleVideoAnimations
    ];
    handlers.forEach(function(handler) {
      protoExpectations.push.apply(protoExpectations, handler(
          modelHelper, sortedInputEvents));
    });
    protoExpectations.sort(compareEvents);
    return protoExpectations;
  }

  /**
   * Every keyboard event is a Response.
   */
  function handleKeyboardEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    forEventTypesIn(sortedInputEvents, KEYBOARD_TYPE_NAMES, function(event) {
      var pe = new ProtoExpectation(
          ProtoExpectation.RESPONSE_TYPE, KEYBOARD_IR_NAME);
      pe.pushEvent(event);
      protoExpectations.push(pe);
    });
    return protoExpectations;
  }

  /**
   * Some mouse events can be translated directly into Responses.
   */
  function handleMouseResponseEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    forEventTypesIn(
        sortedInputEvents, MOUSE_RESPONSE_TYPE_NAMES, function(event) {
      var pe = new ProtoExpectation(
          ProtoExpectation.RESPONSE_TYPE, MOUSE_IR_NAME);
      pe.pushEvent(event);
      protoExpectations.push(pe);
    });
    return protoExpectations;
  }
  /**
   * MouseWheel events are caused either by a physical wheel on a physical
   * mouse, or by a touch-drag gesture on a track-pad. The physical wheel
   * causes MouseWheel events that are much more spaced out, and have no
   * chance of hitting 60fps, so they are each turned into separate Response
   * IRs. The track-pad causes MouseWheel events that are much closer
   * together, and are expected to be 60fps, so the first event in a sequence
   * is turned into a Response, and the rest are merged into an Animation.
   * NB this threshold uses the two events' start times, unlike
   * ProtoExpectation.isNear, which compares the end time of the previous event
   * with the start time of the next.
   */
  function handleMouseWheelEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    var currentPE = undefined;
    var prevEvent_ = undefined;
    forEventTypesIn(
        sortedInputEvents, MOUSE_WHEEL_TYPE_NAMES, function(event) {
      // Switch prevEvent in one place so that we can early-return later.
      var prevEvent = prevEvent_;
      prevEvent_ = event;

      if (currentPE &&
          (prevEvent.start + MOUSE_WHEEL_THRESHOLD_MS) >= event.start) {
        if (currentPE.irType === ProtoExpectation.ANIMATION_TYPE) {
          currentPE.pushEvent(event);
        } else {
          currentPE = new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,
              MOUSEWHEEL_IR_NAME);
          currentPE.pushEvent(event);
          protoExpectations.push(currentPE);
        }
        return;
      }
      currentPE = new ProtoExpectation(
          ProtoExpectation.RESPONSE_TYPE, MOUSEWHEEL_IR_NAME);
      currentPE.pushEvent(event);
      protoExpectations.push(currentPE);
    });
    return protoExpectations;
  }

  /**
   * Down events followed closely by Up events are click Responses, but the
   * Response doesn't start until the Up event.
   *
   *     RRR
   * DDD UUU
   *
   * If there are any Move events in between a Down and an Up, then the Down
   * and the first Move are a Response, then the rest of the Moves are an
   * Animation:
   *
   * RRRRRRRAAAAAAAAAAAAAAAAAAAA
   * DDD MMM MMM MMM MMM MMM UUU
   */
  function handleMouseDragEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    var currentPE = undefined;
    var mouseDownEvent = undefined;
    forEventTypesIn(
        sortedInputEvents, MOUSE_DRAG_TYPE_NAMES, function(event) {
      switch (event.typeName) {
        case INPUT_TYPE.MOUSE_DOWN:
          if (causedFrame(event)) {
            var pe = new ProtoExpectation(
                ProtoExpectation.RESPONSE_TYPE, MOUSE_IR_NAME);
            pe.pushEvent(event);
            protoExpectations.push(pe);
          } else {
            // Responses typically don't start until the mouse up event.
            // Add this MouseDown to the Response that starts at the MouseUp.
            mouseDownEvent = event;
          }
          break;

          // There may be more than 100ms between the start of the mouse down
          // and the start of the mouse up. Chrome and the web don't start to
          // respond until the mouse up. ResponseIRs start deducting comfort
          // at 100ms duration. If more than that 100ms duration is burned
          // through while waiting for the user to release the
          // mouse button, then ResponseIR will unfairly start deducting
          // comfort before Chrome even has a mouse up to respond to.
          // It is technically possible for a site to afford one response on
          // mouse down and another on mouse up, but that is an edge case. The
          // vast majority of mouse downs are not responses.

        case INPUT_TYPE.MOUSE_MOVE:
          if (!causedFrame(event)) {
            // Ignore MouseMoves that do not affect the screen. They are not
            // part of an interaction record by definition.
            var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
            pe.pushEvent(event);
            protoExpectations.push(pe);
          } else if (!currentPE ||
                      !currentPE.isNear(event, MOUSE_MOVE_THRESHOLD_MS)) {
            // The first MouseMove after a MouseDown or after a while is a
            // Response.
            currentPE = new ProtoExpectation(
                ProtoExpectation.RESPONSE_TYPE, MOUSE_IR_NAME);
            currentPE.pushEvent(event);
            if (mouseDownEvent) {
              currentPE.associatedEvents.push(mouseDownEvent);
              mouseDownEvent = undefined;
            }
            protoExpectations.push(currentPE);
          } else {
            // Merge this event into an Animation.
            if (currentPE.irType === ProtoExpectation.ANIMATION_TYPE) {
              currentPE.pushEvent(event);
            } else {
              currentPE = new ProtoExpectation(
                  ProtoExpectation.ANIMATION_TYPE, MOUSE_IR_NAME);
              currentPE.pushEvent(event);
              protoExpectations.push(currentPE);
            }
          }
          break;

        case INPUT_TYPE.MOUSE_UP:
          if (!mouseDownEvent) {
            var pe = new ProtoExpectation(
                causedFrame(event) ? ProtoExpectation.RESPONSE_TYPE :
                ProtoExpectation.IGNORED_TYPE,
                MOUSE_IR_NAME);
            pe.pushEvent(event);
            protoExpectations.push(pe);
            break;
          }

          if (currentPE) {
            currentPE.pushEvent(event);
          } else {
            currentPE = new ProtoExpectation(
                ProtoExpectation.RESPONSE_TYPE, MOUSE_IR_NAME);
            if (mouseDownEvent)
              currentPE.associatedEvents.push(mouseDownEvent);
            currentPE.pushEvent(event);
            protoExpectations.push(currentPE);
          }
          mouseDownEvent = undefined;
          currentPE = undefined;
          break;
      }
    });
    if (mouseDownEvent) {
      currentPE = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
      currentPE.pushEvent(mouseDownEvent);
      protoExpectations.push(currentPE);
    }
    return protoExpectations;
  }

  /**
   * Solitary Tap events are simple Responses:
   *
   * RRR
   * TTT
   *
   * TapDowns are part of Responses.
   *
   * RRRRRRR
   * DDD TTT
   *
   * TapCancels are part of Responses, which seems strange. They always go
   * with scrolls, so they'll probably be merged with scroll Responses.
   * TapCancels can take a significant amount of time and account for a
   * significant amount of work, which should be grouped with the scroll IRs
   * if possible.
   *
   * RRRRRRR
   * DDD CCC
   **/
  function handleTapResponseEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    var currentPE = undefined;
    forEventTypesIn(sortedInputEvents, TAP_TYPE_NAMES, function(event) {
      switch (event.typeName) {
        case INPUT_TYPE.TAP_DOWN:
          currentPE = new ProtoExpectation(
              ProtoExpectation.RESPONSE_TYPE, TAP_IR_NAME);
          currentPE.pushEvent(event);
          protoExpectations.push(currentPE);
          break;

        case INPUT_TYPE.TAP:
          if (currentPE) {
            currentPE.pushEvent(event);
          } else {
            // Sometimes we get Tap events with no TapDown, sometimes we get
            // TapDown events. Handle both.
            currentPE = new ProtoExpectation(
                ProtoExpectation.RESPONSE_TYPE, TAP_IR_NAME);
            currentPE.pushEvent(event);
            protoExpectations.push(currentPE);
          }
          currentPE = undefined;
          break;

        case INPUT_TYPE.TAP_CANCEL:
          if (!currentPE) {
            var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
            pe.pushEvent(event);
            protoExpectations.push(pe);
            break;
          }

          if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
            currentPE.pushEvent(event);
          } else {
            currentPE = new ProtoExpectation(
                ProtoExpectation.RESPONSE_TYPE, TAP_IR_NAME);
            currentPE.pushEvent(event);
            protoExpectations.push(currentPE);
          }
          currentPE = undefined;
          break;
      }
    });
    return protoExpectations;
  }

  /**
   * The PinchBegin and the first PinchUpdate comprise a Response, then the
   * rest of the PinchUpdates comprise an Animation.
   *
   * RRRRRRRAAAAAAAAAAAAAAAAAAAA
   * BBB UUU UUU UUU UUU UUU EEE
   */
  function handlePinchEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    var currentPE = undefined;
    var sawFirstUpdate = false;
    var modelBounds = modelHelper.model.bounds;
    forEventTypesIn(sortedInputEvents, PINCH_TYPE_NAMES, function(event) {
      switch (event.typeName) {
        case INPUT_TYPE.PINCH_BEGIN:
          if (currentPE &&
              currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
            currentPE.pushEvent(event);
            break;
          }
          currentPE = new ProtoExpectation(
              ProtoExpectation.RESPONSE_TYPE, PINCH_IR_NAME);
          currentPE.pushEvent(event);
          currentPE.isAnimationBegin = true;
          protoExpectations.push(currentPE);
          sawFirstUpdate = false;
          break;

        case INPUT_TYPE.PINCH_UPDATE:
          // Like ScrollUpdates, the Begin and the first Update constitute a
          // Response, then the rest of the Updates constitute an Animation
          // that begins when the Response ends. If the user pauses in the
          // middle of an extended pinch gesture, then multiple Animations
          // will be created.
          if (!currentPE ||
              ((currentPE.irType === ProtoExpectation.RESPONSE_TYPE) &&
                sawFirstUpdate) ||
              !currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
            currentPE = new ProtoExpectation(
                ProtoExpectation.ANIMATION_TYPE, PINCH_IR_NAME);
            currentPE.pushEvent(event);
            protoExpectations.push(currentPE);
          } else {
            currentPE.pushEvent(event);
            sawFirstUpdate = true;
          }
          break;

        case INPUT_TYPE.PINCH_END:
          if (currentPE) {
            currentPE.pushEvent(event);
          } else {
            var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
            pe.pushEvent(event);
            protoExpectations.push(pe);
          }
          currentPE = undefined;
          break;
      }
    });
    return protoExpectations;
  }

  /**
   * Flings are defined by 3 types of events: FlingStart, FlingCancel, and the
   * renderer fling event. Flings do not begin with a Response. Flings end
   * either at the beginning of a FlingCancel, or at the end of the renderer
   * fling event.
   *
   * AAAAAAAAAAAAAAAAAAAAAAAAAA
   * SSS
   *     RRRRRRRRRRRRRRRRRRRRRR
   *
   *
   * AAAAAAAAAAA
   * SSS        CCC
   */
  function handleFlingEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    var currentPE = undefined;

    function isRendererFling(event) {
      return event.title === RENDERER_FLING_TITLE;
    }
    var browserHelper = modelHelper.browserHelper;
    var flingEvents = browserHelper.getAllAsyncSlicesMatching(
        isRendererFling);

    forEventTypesIn(sortedInputEvents, FLING_TYPE_NAMES, function(event) {
      flingEvents.push(event);
    });
    flingEvents.sort(compareEvents);

    flingEvents.forEach(function(event) {
      if (event.title === RENDERER_FLING_TITLE) {
        if (currentPE) {
          currentPE.pushEvent(event);
        } else {
          currentPE = new ProtoExpectation(
              ProtoExpectation.ANIMATION_TYPE, FLING_IR_NAME);
          currentPE.pushEvent(event);
          protoExpectations.push(currentPE);
        }
        return;
      }

      switch (event.typeName) {
        case INPUT_TYPE.FLING_START:
          if (currentPE) {
            console.error('Another FlingStart? File a bug with this trace!');
            currentPE.pushEvent(event);
          } else {
            currentPE = new ProtoExpectation(
                ProtoExpectation.ANIMATION_TYPE, FLING_IR_NAME);
            currentPE.pushEvent(event);
            // Set end to an invalid value so that it can be noticed and fixed
            // later.
            currentPE.end = 0;
            protoExpectations.push(currentPE);
          }
          break;

        case INPUT_TYPE.FLING_CANCEL:
          if (currentPE) {
            currentPE.pushEvent(event);
            // FlingCancel events start when TouchStart events start, which is
            // typically when a Response starts. FlingCancel events end when
            // chrome acknowledges them, not when they update the screen. So
            // there might be one more frame during the FlingCancel, after
            // this Animation ends. That won't affect the scoring algorithms,
            // and it will make the IRs look more correct if they don't
            // overlap unnecessarily.
            currentPE.end = event.start;
            currentPE = undefined;
          } else {
            var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
            pe.pushEvent(event);
            protoExpectations.push(pe);
          }
          break;
      }
    });
    // If there was neither a FLING_CANCEL nor a renderer fling after the
    // FLING_START, then assume that it ends at the end of the model, so set
    // the end of currentPE to the end of the model.
    if (currentPE && !currentPE.end)
      currentPE.end = modelHelper.model.bounds.max;
    return protoExpectations;
  }

  /**
   * The TouchStart and the first TouchMove comprise a Response, then the
   * rest of the TouchMoves comprise an Animation.
   *
   * RRRRRRRAAAAAAAAAAAAAAAAAAAA
   * SSS MMM MMM MMM MMM MMM EEE
   *
   * If there are no TouchMove events in between a TouchStart and a TouchEnd,
   * then it's just a Response.
   *
   * RRRRRRR
   * SSS EEE
   */
  function handleTouchEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    var currentPE = undefined;
    var sawFirstMove = false;
    forEventTypesIn(sortedInputEvents, TOUCH_TYPE_NAMES, function(event) {
      switch (event.typeName) {
        case INPUT_TYPE.TOUCH_START:
          if (currentPE) {
            // NB: currentPE will probably be merged with something from
            // handlePinchEvents(). Multiple TouchStart events without an
            // intervening TouchEnd logically implies that multiple fingers
            // are on the screen, so this is probably a pinch gesture.
            currentPE.pushEvent(event);
          } else {
            currentPE = new ProtoExpectation(
                ProtoExpectation.RESPONSE_TYPE, TOUCH_IR_NAME);
            currentPE.pushEvent(event);
            currentPE.isAnimationBegin = true;
            protoExpectations.push(currentPE);
            sawFirstMove = false;
          }
          break;

        case INPUT_TYPE.TOUCH_MOVE:
          if (!currentPE) {
            currentPE = new ProtoExpectation(
                ProtoExpectation.ANIMATION_TYPE, TOUCH_IR_NAME);
            currentPE.pushEvent(event);
            protoExpectations.push(currentPE);
            break;
          }

          // Like Scrolls and Pinches, the Response is defined to be the
          // TouchStart plus the first TouchMove, then the rest of the
          // TouchMoves constitute an Animation.
          if ((sawFirstMove &&
              (currentPE.irType === ProtoExpectation.RESPONSE_TYPE)) ||
              !currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
            // If there's already a touchmove in the currentPE or it's not
            // near event, then finish it and start a new animation.
            var prevEnd = currentPE.end;
            currentPE = new ProtoExpectation(
                ProtoExpectation.ANIMATION_TYPE, TOUCH_IR_NAME);
            currentPE.pushEvent(event);
            // It's possible for there to be a gap between TouchMoves, but
            // that doesn't mean that there should be an Idle IR there.
            currentPE.start = prevEnd;
            protoExpectations.push(currentPE);
          } else {
            currentPE.pushEvent(event);
            sawFirstMove = true;
          }
          break;

        case INPUT_TYPE.TOUCH_END:
          if (!currentPE) {
            var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
            pe.pushEvent(event);
            protoExpectations.push(pe);
            break;
          }
          if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) {
            currentPE.pushEvent(event);
          } else {
            var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
            pe.pushEvent(event);
            protoExpectations.push(pe);
          }
          currentPE = undefined;
          break;
      }
    });
    return protoExpectations;
  }

  /**
   * The first ScrollBegin and the first ScrollUpdate comprise a Response,
   * then the rest comprise an Animation.
   *
   * RRRRRRRAAAAAAAAAAAAAAAAAAAA
   * BBB UUU UUU UUU UUU UUU EEE
   */
  function handleScrollEvents(modelHelper, sortedInputEvents) {
    var protoExpectations = [];
    var currentPE = undefined;
    var sawFirstUpdate = false;
    forEventTypesIn(sortedInputEvents, SCROLL_TYPE_NAMES, function(event) {
      switch (event.typeName) {
        case INPUT_TYPE.SCROLL_BEGIN:
          // Always begin a new PE even if there already is one, unlike
          // PinchBegin.
          currentPE = new ProtoExpectation(
              ProtoExpectation.RESPONSE_TYPE, SCROLL_IR_NAME);
          currentPE.pushEvent(event);
          currentPE.isAnimationBegin = true;
          protoExpectations.push(currentPE);
          sawFirstUpdate = false;
          break;

        case INPUT_TYPE.SCROLL_UPDATE:
          if (currentPE) {
            if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS) &&
                ((currentPE.irType === ProtoExpectation.ANIMATION_TYPE) ||
                !sawFirstUpdate)) {
              currentPE.pushEvent(event);
              sawFirstUpdate = true;
            } else {
              currentPE = new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,
                  SCROLL_IR_NAME);
              currentPE.pushEvent(event);
              protoExpectations.push(currentPE);
            }
          } else {
             // ScrollUpdate without ScrollBegin.
            currentPE = new ProtoExpectation(
                ProtoExpectation.ANIMATION_TYPE, SCROLL_IR_NAME);
            currentPE.pushEvent(event);
            protoExpectations.push(currentPE);
          }
          break;

        case INPUT_TYPE.SCROLL_END:
          if (!currentPE) {
            console.error('ScrollEnd without ScrollUpdate? ' +
                          'File a bug with this trace!');
            var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);
            pe.pushEvent(event);
            protoExpectations.push(pe);
            break;
          }
          currentPE.pushEvent(event);
          break;
      }
    });
    return protoExpectations;
  }

  /**
   * Returns proto expectations for video animation events.
   *
   * Video animations represent video playback, and are based on
   * VideoPlayback async events (going from the VideoFrameCompositor::Start
   * to VideoFrameCompositor::Stop calls)
   */
  function handleVideoAnimations(modelHelper, sortedInputEvents) {
    var events = [];
    for (var pid in modelHelper.rendererHelpers) {
      for (var asyncSlice of
          modelHelper.rendererHelpers[pid].mainThread.asyncSliceGroup.slices) {
        if (asyncSlice.title === PLAYBACK_EVENT_TITLE)
          events.push(asyncSlice);
      }
    }

    events.sort(tr.importer.compareEvents);

    var protoExpectations = [];
    for (var event of events) {
      var currentPE = new ProtoExpectation(
          ProtoExpectation.ANIMATION_TYPE, VIDEO_IR_NAME);
      currentPE.start = event.start;
      currentPE.end = event.end;
      currentPE.pushEvent(event);
      protoExpectations.push(currentPE);
    }

    return protoExpectations;
  }

  /**
   * CSS Animations are merged into AnimationExpectations when they intersect.
   */
  function handleCSSAnimations(modelHelper, sortedInputEvents) {
    // First find all the top-level CSS Animation async events.
    var animationEvents = modelHelper.browserHelper.
        getAllAsyncSlicesMatching(function(event) {
          return ((event.title === CSS_ANIMATION_TITLE) &&
                  event.isTopLevel &&
                  (event.duration > 0));
    });


    // Time ranges where animations are actually running will be collected here.
    // Each element will contain {min, max, animation}.
    var animationRanges = [];

    // This helper function will be called when a time range is found
    // during which the animation is actually running.
    function pushAnimationRange(start, end, animation) {
      var range = tr.b.Range.fromExplicitRange(start, end);
      range.animation = animation;
      animationRanges.push(range);
    }

    animationEvents.forEach(function(animation) {
      if (animation.subSlices.length === 0) {
        pushAnimationRange(animation.start, animation.end, animation);
      } else {
        // Now run a state machine over the animation's subSlices, which
        // indicate the animations running/paused/finished states, in order to
        // find ranges where the animation was actually running.
        var start = undefined;
        animation.subSlices.forEach(function(sub) {
          if ((sub.args.data.state === 'running') &&
              (start === undefined)) {
            // It's possible for the state to alternate between running and
            // pending, but the animation is still running in that case,
            // so only set start if the state is changing from one of the halted
            // states.
            start = sub.start;
          } else if ((sub.args.data.state === 'paused') ||
                     (sub.args.data.state === 'idle') ||
                     (sub.args.data.state === 'finished')) {
            if (start === undefined) {
              // An animation was already running when the trace started.
              // (Actually, it's possible that the animation was in the 'idle'
              // state when tracing started, but that should be rare, and will
              // be fixed when async events are buffered.)
              // http: //crbug.com/565627
              start = modelHelper.model.bounds.min;
            }

            pushAnimationRange(start, sub.start, animation);
            start = undefined;
          }
        });

        // An animation was still running when the
        // top-level animation event ended.
        if (start !== undefined)
          pushAnimationRange(start, animation.end, animation);
      }
    });

    // Now we have a set of time ranges when css animations were actually
    // running.
    // Leave merging intersecting animations to mergeIntersectingAnimations(),
    // after findFrameEventsForAnimations removes frame-less animations.

    return animationRanges.map(function(range) {
      var protoExpectation = new ProtoExpectation(
          ProtoExpectation.ANIMATION_TYPE, CSS_IR_NAME);
      protoExpectation.start = range.min;
      protoExpectation.end = range.max;
      protoExpectation.associatedEvents.push(range.animation);
      return protoExpectation;
    });
  }

  /**
   * Get all the events (prepareMailbox and serviceScriptedAnimations)
   * relevant to WebGL. Note that modelHelper is the helper object containing
   * the model, and mailboxEvents and animationEvents are arrays where the
   * events are being pushed into (DrawingBuffer::prepareMailbox events go
   * into mailboxEvents; PageAnimator::serviceScriptedAnimations events go
   * into animationEvents). The function does not return anything but
   * modifies mailboxEvents and animationEvents.
   */
  function findWebGLEvents(modelHelper, mailboxEvents, animationEvents) {
    for (var event of modelHelper.model.getDescendantEvents()) {
      if (event.title === 'DrawingBuffer::prepareMailbox')
        mailboxEvents.push(event);
      else if (event.title === 'PageAnimator::serviceScriptedAnimations')
        animationEvents.push(event);
    }
  }

  /**
   * Returns a list of events in mailboxEvents that have an event in
   * animationEvents close by (within ANIMATION_MERGE_THRESHOLD_MS).
   */
  function findMailboxEventsNearAnimationEvents(
      mailboxEvents, animationEvents) {
    if (animationEvents.length === 0)
      return [];

    mailboxEvents.sort(compareEvents);
    animationEvents.sort(compareEvents);
    var animationIterator = animationEvents[Symbol.iterator]();
    var animationEvent = animationIterator.next().value;

    var filteredEvents = [];

    // We iterate through the mailboxEvents. With each event, we check if
    // there is a animationEvent near it, and if so, add it to the result.
    for (var event of mailboxEvents) {
      // If the current animationEvent is too far before the mailboxEvent,
      // we advance until we get to the next animationEvent that is not too
      // far before the animationEvent.
      while (animationEvent &&
          (animationEvent.start < (
           event.start - ANIMATION_MERGE_THRESHOLD_MS)))
        animationEvent = animationIterator.next().value;

      // If there aren't any more animationEvents, then that means all the
      // remaining mailboxEvents are too far after the animationEvents, so
      // we can quit now.
      if (!animationEvent)
        break;

      // If there's a animationEvent close to the mailboxEvent, then we push
      // the current mailboxEvent onto the stack.
      if (animationEvent.start < (event.start + ANIMATION_MERGE_THRESHOLD_MS))
        filteredEvents.push(event);
    }
    return filteredEvents;
  }

  /**
   * Merge consecutive mailbox events into a ProtoExpectation. Note: Only
   * the drawingBuffer::prepareMailbox events will end up in the
   * associatedEvents. The PageAnimator::serviceScriptedAnimations events
   * will not end up in the associatedEvents.
   */
  function createProtoExpectationsFromMailboxEvents(mailboxEvents) {
    var protoExpectations = [];
    var currentPE = undefined;
    for (var event of mailboxEvents) {
      if (currentPE === undefined || !currentPE.isNear(
          event, ANIMATION_MERGE_THRESHOLD_MS)) {
        currentPE = new ProtoExpectation(
            ProtoExpectation.ANIMATION_TYPE, WEBGL_IR_NAME);
        currentPE.pushEvent(event);
        protoExpectations.push(currentPE);
      }
      else {
        currentPE.pushEvent(event);
      }
    }
    return protoExpectations;
  }

  // WebGL animations are identified by the DrawingBuffer::prepareMailbox
  // and PageAnimator::serviceScriptedAnimations events (one of each per frame)
  // and consecutive frames are merged into the same animation.
  function handleWebGLAnimations(modelHelper, sortedInputEvents) {
    // Get the prepareMailbox and scriptedAnimation events.
    var prepareMailboxEvents = [];
    var scriptedAnimationEvents = [];

    findWebGLEvents(modelHelper, prepareMailboxEvents, scriptedAnimationEvents);
    var webGLMailboxEvents = findMailboxEventsNearAnimationEvents(
        prepareMailboxEvents, scriptedAnimationEvents);

    return createProtoExpectationsFromMailboxEvents(webGLMailboxEvents);
  }


  function postProcessProtoExpectations(modelHelper, protoExpectations) {
    // protoExpectations is input only. Returns a modified set of
    // ProtoExpectations.  The order is important.
    protoExpectations = findFrameEventsForAnimations(
        modelHelper, protoExpectations);
    protoExpectations = mergeIntersectingResponses(protoExpectations);
    protoExpectations = mergeIntersectingAnimations(protoExpectations);
    protoExpectations = fixResponseAnimationStarts(protoExpectations);
    protoExpectations = fixTapResponseTouchAnimations(protoExpectations);
    return protoExpectations;
  }

  /**
   * TouchStarts happen at the same time as ScrollBegins.
   * It's easier to let multiple handlers create multiple overlapping
   * Responses and then merge them, rather than make the handlers aware of the
   * other handlers' PEs.
   *
   * For example:
   * RR
   *  RRR  -> RRRRR
   *    RR
   *
   * protoExpectations is input only.
   * Returns a modified set of ProtoExpectations.
   */
  function mergeIntersectingResponses(protoExpectations) {
    var newPEs = [];
    while (protoExpectations.length) {
      var pe = protoExpectations.shift();
      newPEs.push(pe);

      // Only consider Responses for now.
      if (pe.irType !== ProtoExpectation.RESPONSE_TYPE)
        continue;

      for (var i = 0; i < protoExpectations.length; ++i) {
        var otherPE = protoExpectations[i];

        if (otherPE.irType !== pe.irType)
          continue;

        if (!otherPE.intersects(pe))
          continue;

        // Don't merge together Responses of the same type.
        // If handleTouchEvents wanted two of its Responses to be merged, then
        // it would have made them that way to begin with.
        var typeNames = pe.associatedEvents.map(function(event) {
          return event.typeName;
        });
        if (otherPE.containsTypeNames(typeNames))
          continue;

        pe.merge(otherPE);
        protoExpectations.splice(i, 1);

        // Don't skip the next otherPE!
        --i;
      }
    }
    return newPEs;
  }

  /**
   * An animation is simply an expectation of 60fps between start and end.
   * If two animations overlap, then merge them.
   *
   * For example:
   * AA
   *  AAA  -> AAAAA
   *    AA
   *
   * protoExpectations is input only.
   * Returns a modified set of ProtoExpectations.
   */
  function mergeIntersectingAnimations(protoExpectations) {
    var newPEs = [];
    while (protoExpectations.length) {
      var pe = protoExpectations.shift();
      newPEs.push(pe);

      // Only consider Animations for now.
      if (pe.irType !== ProtoExpectation.ANIMATION_TYPE)
        continue;

      var isCSS = pe.containsSliceTitle(CSS_ANIMATION_TITLE);
      var isFling = pe.containsTypeNames([INPUT_TYPE.FLING_START]);
      var isVideo = pe.containsTypeNames([VIDEO_IR_NAME]);

      for (var i = 0; i < protoExpectations.length; ++i) {
        var otherPE = protoExpectations[i];

        if (otherPE.irType !== pe.irType)
          continue;

        // Don't merge CSS Animations with any other types.
        if (isCSS != otherPE.containsSliceTitle(CSS_ANIMATION_TITLE))
          continue;

        if (isCSS) {
          if (!pe.isNear(otherPE, ANIMATION_MERGE_THRESHOLD_MS))
            continue;
        } else if (!otherPE.intersects(pe)) {
          continue;
        }

        // Don't merge Fling Animations with any other types.
        if (isFling !== otherPE.containsTypeNames([INPUT_TYPE.FLING_START]))
          continue;

        // Don't merge Video Animations with any other types.
        if (isVideo !== otherPE.containsTypeNames([VIDEO_IR_NAME]))
          continue;

        pe.merge(otherPE);
        protoExpectations.splice(i, 1);
        // Don't skip the next otherPE!
        --i;
      }
    }
    return newPEs;
  }

  /**
   * The ends of responses frequently overlap the starts of animations.
   * Fix the animations to reflect the fact that the user can only start to
   * expect 60fps after the response.
   *
   * For example:
   * RRR   -> RRRAA
   *  AAAA
   *
   * protoExpectations is input only.
   * Returns a modified set of ProtoExpectations.
   */
  function fixResponseAnimationStarts(protoExpectations) {
    protoExpectations.forEach(function(ape) {
      // Only consider animations for now.
      if (ape.irType !== ProtoExpectation.ANIMATION_TYPE)
        return;

      protoExpectations.forEach(function(rpe) {
        // Only consider responses for now.
        if (rpe.irType !== ProtoExpectation.RESPONSE_TYPE)
          return;

        // Only consider responses that end during the animation.
        if (!ape.containsTimestampInclusive(rpe.end))
          return;

        // Ignore Responses that are entirely contained by the animation.
        if (ape.containsTimestampInclusive(rpe.start))
          return;

        // Move the animation start to the response end.
        ape.start = rpe.end;
      });
    });
    return protoExpectations;
  }

  /**
   * Merge Tap Responses that overlap Touch-only Animations.
   * https: *github.com/catapult-project/catapult/issues/1431
   */
  function fixTapResponseTouchAnimations(protoExpectations) {
    function isTapResponse(pe) {
      return (pe.irType === ProtoExpectation.RESPONSE_TYPE) &&
              pe.containsTypeNames([INPUT_TYPE.TAP]);
    }
    function isTouchAnimation(pe) {
      return (pe.irType === ProtoExpectation.ANIMATION_TYPE) &&
              pe.containsTypeNames([INPUT_TYPE.TOUCH_MOVE]) &&
              !pe.containsTypeNames([
                  INPUT_TYPE.SCROLL_UPDATE, INPUT_TYPE.PINCH_UPDATE]);
    }
    var newPEs = [];
    while (protoExpectations.length) {
      var pe = protoExpectations.shift();
      newPEs.push(pe);

      // protoExpectations are sorted by start time, and we don't know whether
      // the Tap Response or the Touch Animation will be first
      var peIsTapResponse = isTapResponse(pe);
      var peIsTouchAnimation = isTouchAnimation(pe);
      if (!peIsTapResponse && !peIsTouchAnimation)
        continue;

      for (var i = 0; i < protoExpectations.length; ++i) {
        var otherPE = protoExpectations[i];

        if (!otherPE.intersects(pe))
          continue;

        if (peIsTapResponse && !isTouchAnimation(otherPE))
          continue;

        if (peIsTouchAnimation && !isTapResponse(otherPE))
          continue;

        // pe might be the Touch Animation, but the merged ProtoExpectation
        // should be a Response.
        pe.irType = ProtoExpectation.RESPONSE_TYPE;

        pe.merge(otherPE);
        protoExpectations.splice(i, 1);
        // Don't skip the next otherPE!
        --i;
      }
    }
    return newPEs;
  }

  function findFrameEventsForAnimations(modelHelper, protoExpectations) {
    var newPEs = [];
    var frameEventsByPid = getSortedFrameEventsByProcess(modelHelper);

    for (var pe of protoExpectations) {
      if (pe.irType !== ProtoExpectation.ANIMATION_TYPE) {
        newPEs.push(pe);
        continue;
      }

      var frameEvents = [];
      // TODO(benjhayden): Use frame blame contexts here.
      for (var pid of Object.keys(modelHelper.rendererHelpers)) {
        var range = tr.b.Range.fromExplicitRange(pe.start, pe.end);
        frameEvents.push.apply(frameEvents,
            range.filterArray(frameEventsByPid[pid], e => e.start));
      }

      // If a tree falls in a forest...
      // If there were not actually any frames while the animation was
      // running, then it wasn't really an animation, now, was it?
      // Philosophy aside, the system_health Animation metrics fail hard if
      // there are no frames in an AnimationExpectation.
      // Since WebGL animations don't generate this type of frame event,
      // don't remove them if it's a WebGL animation.
      // TODO(alexandermont): Identify what the correct frame event to
      // use here is.
      if (frameEvents.length === 0 && !pe.names.has(WEBGL_IR_NAME)) {
        pe.irType = ProtoExpectation.IGNORED_TYPE;
        newPEs.push(pe);
        continue;
      }

      pe.associatedEvents.addEventSet(frameEvents);
      newPEs.push(pe);
    }

    return newPEs;
  }

  /**
   * Check that none of the handlers accidentally ignored an input event.
   */
  function checkAllInputEventsHandled(sortedInputEvents, protoExpectations) {
    var handledEvents = [];
    protoExpectations.forEach(function(protoExpectation) {
      protoExpectation.associatedEvents.forEach(function(event) {
        // Ignore CSS Animations that might have multiple active ranges.
        if ((event.title === CSS_ANIMATION_TITLE) &&
            (event.subSlices.length > 0))
          return;

        if ((handledEvents.indexOf(event) >= 0) &&
            (event.title !== tr.model.helpers.IMPL_RENDERING_STATS)) {
          console.error('double-handled event', event.typeName,
              parseInt(event.start), parseInt(event.end), protoExpectation);
          return;
        }
        handledEvents.push(event);
      });
    });

    sortedInputEvents.forEach(function(event) {
      if (handledEvents.indexOf(event) < 0) {
        console.error('UNHANDLED INPUT EVENT!',
            event.typeName, parseInt(event.start), parseInt(event.end));
      }
    });
  }

  /**
   * Find ProtoExpectations, post-process them, convert them to real IRs.
   */
  function findInputExpectations(modelHelper) {
    var sortedInputEvents = getSortedInputEvents(modelHelper);
    var protoExpectations = findProtoExpectations(
        modelHelper, sortedInputEvents);
    protoExpectations = postProcessProtoExpectations(
        modelHelper, protoExpectations);
    checkAllInputEventsHandled(sortedInputEvents, protoExpectations);

    var irs = [];
    protoExpectations.forEach(function(protoExpectation) {
      var ir = protoExpectation.createInteractionRecord(modelHelper.model);
      if (ir)
        irs.push(ir);
    });
    return irs;
  }

  return {
    findInputExpectations: findInputExpectations,
    compareEvents: compareEvents,
    CSS_ANIMATION_TITLE: CSS_ANIMATION_TITLE
  };
});
</script>
