import Ember from 'ember';
import { module, test } from 'qunit';
import Component from '@ember/component';
import {
  setupContext,
  setupRenderingContext,
  teardownContext,
  teardownRenderingContext,
  waitFor,
  render,
} from '@ember/test-helpers';

import hasEmberVersion from 'ember-test-helpers/has-ember-version';
import { setResolverRegistry } from '../helpers/resolver';
import hbs from 'htmlbars-inline-precompile';
import { defer } from 'rsvp';

const PromiseWrapperTemplate = hbs`
{{~#if settled~}}
  {{fulfillmentValue}}
{{~else~}}
  <div class="loading">Please wait</div>
{{~/if}}
`;

const PromiseWrapper = Component.extend({
  init() {
    this._super(...arguments);

    this.promise
      .then(value => this.set('fulfillmentValue', value))
      .finally(() => this.set('settled', true));
  },
});

module('setupRenderingContext "real world"', function(hooks) {
  if (!hasEmberVersion(2, 4)) {
    return;
  }
  hooks.beforeEach(async function() {
    setResolverRegistry({
      'component:promise-wrapper': PromiseWrapper,
      'template:components/promise-wrapper': PromiseWrapperTemplate,
    });

    await setupContext(this);
    await setupRenderingContext(this);

    this._waiter = () => {
      return !this.isWaiterPending;
    };

    // In Ember < 2.8 `registerWaiter` expected to be bound to
    // `Ember.Test` 😭
    //
    // Once we have dropped support for < 2.8 we should swap this to
    // use:
    //
    // import { registerWaiter } from '@ember/test';
    Ember.Test.registerWaiter(this._waiter);
  });

  hooks.afterEach(async function() {
    Ember.Test.unregisterWaiter(this._waiter);
    await teardownRenderingContext(this);
    await teardownContext(this);
  });

  test('can check element while waiting for settled state', async function(assert) {
    let deferred = defer();
    this.set('promise', deferred.promise);

    // force the waiter to pause, emulating a pending AJAX or fetch request
    this.isWaiterPending = true;

    // Does not use `await` intentionally
    let renderPromise = render(hbs`{{promise-wrapper promise=promise }}`);

    await waitFor('.loading');

    assert.equal(this.element.textContent, 'Please wait', 'has pending content');

    deferred.resolve('Yippie!');

    // release the waiter, so `settled` from `render` will complete
    this.isWaiterPending = false;

    await renderPromise;

    assert.equal(this.element.textContent, 'Yippie!', 'has fulfillment value');
  });
});

@@ -218,16 +218,25 @@
 render,%0A
+  click,%0A
 %7D from '
@@ -823,16 +823,338 @@
 %7D,%0A%7D);%0A%0A
+const ClickMeButtonTemplate = hbs%60%0A%7B%7B~#if wasClicked~%7D%7D%0A  Clicked!%0A%7B%7B~else~%7D%7D%0A  Click Me!%0A%7B%7B~/if~%7D%7D%0A%60;%0A%0Aconst ClickMeButtonComponent = Component.extend(%7B%0A  classNames: %5B'click-me-button'%5D,%0A  init() %7B%0A    this._super(...arguments);%0A    this.wasClicked = false;%0A  %7D,%0A%0A  click() %7B%0A    this.set('wasClicked', true);%0A  %7D,%0A%7D);%0A%0A
 module('
@@ -1439,16 +1439,144 @@
 emplate,
+%0A%0A      'component:click-me-button': ClickMeButtonComponent,%0A      'template:components/click-me-button': ClickMeButtonTemplate,
 %0A    %7D);
@@ -2912,18 +2912,1100 @@
 alue');%0A
-
   %7D);
+%0A%0A  // uses %60%7B%7B-in-element%60 which was only added in Ember 2.10%0A  if (hasEmberVersion(2, 10)) %7B%0A    test('can click on a sibling element of this.element (within the rootElement)', async function(assert) %7B%0A      let rootElement = document.getElementById('ember-testing');%0A%0A      assert.notEqual(%0A        rootElement,%0A        this.element,%0A        'precond - confirm that the rootElement is different from this.element'%0A      );%0A%0A      this.set('rootElement', rootElement);%0A%0A      await render(hbs%60%7B%7B#-in-element rootElement%7D%7D%7B%7Bclick-me-button%7D%7D%7B%7B/-in-element%7D%7D%60);%0A%0A      // this will need to be modified / removed once RFC280 lands%0A      assert.equal(this.element.textContent, '', 'no content is contained _within_ this.element');%0A      assert.equal(%0A        rootElement.textContent,%0A        'Click Me!',%0A        'the rootElement has the correct content after initial render'%0A      );%0A%0A      await click('.click-me-button');%0A%0A      assert.equal(%0A        rootElement.textContent,%0A        'Clicked!',%0A        'the rootElement has the correct content after clicking'%0A      );%0A    %7D);%0A  %7D
 %0A%7D);%0A

add failing test for sibling content in rootElement