'use strict';

/**
  ResizeTestHelper is a framework to test ResizeObserver
  notifications. Use it to make assertions about ResizeObserverEntries.
  This framework is needed because ResizeObservations are
  delivered asynchronously inside the event loop.

  Features:
  - can queue multiple notification steps in a test
  - handles timeouts
  - returns Promise that is fullfilled when test completes.
    Use to chain tests (since parallel async ResizeObserver tests
    would conflict if reusing same DOM elements).

  Usage:

  create ResizeTestHelper for every test.
  Make assertions inside notify, timeout callbacks.
  Start tests with helper.start()
  Chain tests with Promises.
  Counts animation frames, see startCountingRaf
*/

/*
  @param name: test name
  @param steps:
  {
    setup: function(ResizeObserver) {
      // called at the beginning of the test step
      // your observe/resize code goes here
    },
    notify: function(entries, observer) {
      // ResizeObserver callback.
      // Make assertions here.
      // Return true if next step should start on the next event loop.
    },
    timeout: function() {
      // Define this if your test expects to time out.
      // If undefined, timeout is assert_unreached.
    }
  }
*/
function ResizeTestHelper(name, steps)
{
    this._name = name;
    this._steps = steps || [];
    this._stepIdx = -1;
    this._harnessTest = null;
    this._observer = new ResizeObserver(this._handleNotification.bind(this));
    this._timeoutBind = this._handleTimeout.bind(this);
    this._nextStepBind = this._nextStep.bind(this);
}

ResizeTestHelper.TIMEOUT = 1000;

ResizeTestHelper.prototype = {
  get _currentStep() {
    return this._steps[this._stepIdx];
  },

  _nextStep: function() {
    if (++this._stepIdx == this._steps.length)
      return this._done();
    this._timeoutId = this._harnessTest.step_timeout(
      this._timeoutBind, ResizeTestHelper.TIMEOUT);
    try {
      this._steps[this._stepIdx].setup(this._observer);
    }
    catch(err) {
      this._harnessTest.step(() => {
        assert_unreached("Caught a throw, possible syntax error");
      });
    }
  },

  _handleNotification: function(entries) {
    if (this._timeoutId) {
      window.clearTimeout(this._timeoutId);
      delete this._timeoutId;
    }
    this._harnessTest.step(() => {
      let rafDelay = this._currentStep.notify(entries, this._observer);
      if (rafDelay)
        window.requestAnimationFrame(this._nextStepBind);
      else
        this._nextStep();
    });
  },

  _handleTimeout: function() {
    delete this._timeoutId;
    this._harnessTest.step(() => {
      if (this._currentStep.timeout) {
        this._currentStep.timeout();
      }
      else {
        assert_unreached("Timed out waiting for notification. (" + ResizeTestHelper.TIMEOUT + "ms)");
      }
      this._nextStep();
    });
  },

  _done: function() {
    this._observer.disconnect();
    delete this._observer;
    this._harnessTest.done();
    if (this._rafCountRequest) {
      window.cancelAnimationFrame(this._rafCountRequest);
      delete this._rafCountRequest;
    }
    window.requestAnimationFrame(() => { this._resolvePromise(); });
  },

  start: function() {
    this._harnessTest = async_test(this._name);
    this._harnessTest.step(() => {
      assert_equals(this._stepIdx, -1, "start can only be called once");
      this._nextStep();
    });
    return new Promise( (resolve, reject) => {
      this._resolvePromise = resolve;
      this._rejectPromise = reject;
    });
  },

  get rafCount() {
    if (!this._rafCountRequest)
      throw "rAF count is not active";
    return this._rafCount;
  },

  _incrementRaf: function() {
    if (this._rafCountRequest) {
      this._rafCount++;
      this._rafCountRequest = window.requestAnimationFrame(this._incrementRafBind);
    }
  },

  startCountingRaf: function() {
    if (this._rafCountRequest)
      window.cancelAnimationFrame(this._rafCountRequest);
    if (!this._incrementRafBind)
      this._incrementRafBind = this._incrementRaf.bind(this);
    this._rafCount = 0;
    this._rafCountRequest = window.requestAnimationFrame(this._incrementRafBind);
  }
}
