// Here's how waitForNotification works:
//
// - myTestFunction0()
//   - waitForNotification(myTestFunction1)
//     - requestAnimationFrame()
//   - Modify DOM in a way that should trigger an IntersectionObserver callback.
// - BeginFrame
//   - requestAnimationFrame handler runs
//     - Second requestAnimationFrame()
//   - Style, layout, paint
//   - IntersectionObserver generates new notifications
//     - Posts a task to deliver notifications
// - Task to deliver IntersectionObserver notifications runs
//   - IntersectionObserver callbacks run
// - Second requestAnimationFrameHandler runs
//     - step_timeout()
// - step_timeout handler runs
//   - myTestFunction1()
//     - [optional] waitForNotification(myTestFunction2)
//       - requestAnimationFrame()
//     - Verify newly-arrived IntersectionObserver notifications
//     - [optional] Modify DOM to trigger new notifications
//
// Ideally, it should be sufficient to use requestAnimationFrame followed
// by two step_timeouts, with the first step_timeout firing in between the
// requestAnimationFrame handler and the task to deliver notifications.
// However, the precise timing of requestAnimationFrame, the generation of
// a new display frame (when IntersectionObserver notifications are
// generated), and the delivery of these events varies between engines, making
// this tricky to test in a non-flaky way.
//
// In particular, in WebKit, requestAnimationFrame and the generation of
// a display frame are two separate tasks, so a step_timeout called within
// requestAnimationFrame can fire before a display frame is generated.
//
// In Gecko, on the other hand, requestAnimationFrame and the generation of
// a display frame are a single task, and IntersectionObserver notifications
// are generated during this task. However, the task posted to deliver these
// notifications can fire after the following requestAnimationFrame.
//
// This means that in general, by the time the second requestAnimationFrame
// handler runs, we know that IntersectionObservations have been generated,
// and that a task to deliver these notifications has been posted (though
// possibly not yet delivered). Then, by the time the step_timeout() handler
// runs, these notifications have been delivered.
//
// Since waitForNotification uses a double-rAF, it is now possible that
// IntersectionObservers may have generated more notifications than what is
// under test, but have not yet scheduled the new batch of notifications for
// delivery. As a result, observer.takeRecords should NOT be used in tests:
//
// - myTestFunction0()
//   - waitForNotification(myTestFunction1)
//     - requestAnimationFrame()
//   - Modify DOM in a way that should trigger an IntersectionObserver callback.
// - BeginFrame
//   - requestAnimationFrame handler runs
//     - Second requestAnimationFrame()
//   - Style, layout, paint
//   - IntersectionObserver generates a batch of notifications
//     - Posts a task to deliver notifications
// - Task to deliver IntersectionObserver notifications runs
//   - IntersectionObserver callbacks run
// - BeginFrame
//   - Second requestAnimationFrameHandler runs
//     - step_timeout()
//   - IntersectionObserver generates another batch of notifications
//     - Post task to deliver notifications
// - step_timeout handler runs
//   - myTestFunction1()
//     - At this point, observer.takeRecords will get the second batch of
//       notifications.
function waitForNotification(t, f) {
  requestAnimationFrame(function() {
    requestAnimationFrame(function() { t.step_timeout(f, 0); });
  });
}

// If you need to wait until the IntersectionObserver algorithm has a chance
// to run, but don't need to wait for delivery of the notifications...
function waitForFrame(t, f) {
  requestAnimationFrame(function() {
    t.step_timeout(f, 0);
  });
}

// The timing of when runTestCycle is called is important.  It should be
// called:
//
//   - Before or during the window load event, or
//   - Inside of a prior runTestCycle callback, *before* any assert_* methods
//     are called.
//
// Following these rules will ensure that the test suite will not abort before
// all test steps have run.
//
// If the 'delay' parameter to the IntersectionObserver constructor is used,
// tests will need to add the same delay to their runTestCycle invocations, to
// wait for notifications to be generated and delivered.
function runTestCycle(f, description, delay) {
  async_test(function(t) {
    if (delay) {
      step_timeout(() => {
        waitForNotification(t, t.step_func_done(f));
      }, delay);
    } else {
      waitForNotification(t, t.step_func_done(f));
    }
  }, description);
}

// Root bounds for a root with an overflow clip as defined by:
//   http://wicg.github.io/IntersectionObserver/#intersectionobserver-root-intersection-rectangle
function contentBounds(root) {
  var left = root.offsetLeft + root.clientLeft;
  var right = left + root.clientWidth;
  var top = root.offsetTop + root.clientTop;
  var bottom = top + root.clientHeight;
  return [left, right, top, bottom];
}

// Root bounds for a root without an overflow clip as defined by:
//   http://wicg.github.io/IntersectionObserver/#intersectionobserver-root-intersection-rectangle
function borderBoxBounds(root) {
  var left = root.offsetLeft;
  var right = left + root.offsetWidth;
  var top = root.offsetTop;
  var bottom = top + root.offsetHeight;
  return [left, right, top, bottom];
}

function clientBounds(element) {
  var rect = element.getBoundingClientRect();
  return [rect.left, rect.right, rect.top, rect.bottom];
}

function rectArea(rect) {
  return (rect.left - rect.right) * (rect.bottom - rect.top);
}

function checkRect(actual, expected, description, all) {
  if (!expected.length)
    return;
  assert_equals(actual.left | 0, expected[0] | 0, description + '.left');
  assert_equals(actual.right | 0, expected[1] | 0, description + '.right');
  assert_equals(actual.top | 0, expected[2] | 0, description + '.top');
  assert_equals(actual.bottom | 0, expected[3] | 0, description + '.bottom');
}

function checkLastEntry(entries, i, expected) {
  assert_equals(entries.length, i + 1, 'entries.length');
  if (expected) {
    checkRect(
        entries[i].boundingClientRect, expected.slice(0, 4),
        'entries[' + i + '].boundingClientRect', entries[i]);
    checkRect(
        entries[i].intersectionRect, expected.slice(4, 8),
        'entries[' + i + '].intersectionRect', entries[i]);
    checkRect(
        entries[i].rootBounds, expected.slice(8, 12),
        'entries[' + i + '].rootBounds', entries[i]);
    if (expected.length > 12) {
      assert_equals(
          entries[i].isIntersecting, expected[12],
          'entries[' + i + '].isIntersecting');
    }
  }
}

function checkJsonEntry(actual, expected) {
  checkRect(
      actual.boundingClientRect, expected.boundingClientRect,
      'entry.boundingClientRect');
  checkRect(
      actual.intersectionRect, expected.intersectionRect,
      'entry.intersectionRect');
  if (actual.rootBounds == 'null')
    assert_equals(expected.rootBounds, 'null', 'rootBounds is null');
  else
    checkRect(actual.rootBounds, expected.rootBounds, 'entry.rootBounds');
  assert_equals(actual.isIntersecting, expected.isIntersecting);
  assert_equals(actual.target, expected.target);
}

function checkJsonEntries(actual, expected, description) {
  test(function() {
    assert_equals(actual.length, expected.length);
    for (var i = 0; i < actual.length; i++)
      checkJsonEntry(actual[i], expected[i]);
  }, description);
}

function checkIsIntersecting(entries, i, expected) {
  assert_equals(entries[i].isIntersecting, expected,
    'entries[' + i + '].target.isIntersecting equals ' + expected);
}
