'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 = 500;

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