import { module, test } from 'qunit';
import RSVP from 'rsvp';
import wait from 'ember-test-helpers/wait';
import SearchRequest from 'web-client/utilities/navigation-search/search-request';
import { resolveAfter } from 'web-client/utilities/navigation-search/search-request';

module('utilities/navigation-search/search-request', {
  beforeEach() {
    this.searchRequest = SearchRequest.create();
  },

  afterEach() {
    this.searchRequest.cancel();
  }
});

test('toggles the isWaiting flag according to the delayResults option', function(assert) {
  assert.expect(3);

  let request = RSVP.resolve;

  assert.equal(this.searchRequest.get('isWaiting'), false, 'is not delaying at first');

  this.searchRequest.start({ request, delayResults: 10 });
  assert.equal(this.searchRequest.get('isWaiting'), true, 'is delaying after request has started');

  return wait().then(() => {
    assert.equal(this.searchRequest.get('isWaiting'), false, 'is no longer delaying after request has finished');
  });
});

test('isWaiting is true when delayResults is 0', function(assert) {
  assert.expect(1);

  let request = RSVP.resolve;
  this.searchRequest.start({ request, delayResults: 0 });

  assert.equal(this.searchRequest.get('isWaiting'), true, 'is waiting');
});

test('isLoading while the promise is unfulfilled', function(assert) {
  assert.expect(2);

  let request = RSVP.resolve;

  this.searchRequest.start({ request, delayResults: 0 });

  assert.equal(this.searchRequest.get('isLoading'), true, 'is loading at first');

  return wait().then(() => {
    assert.equal(this.searchRequest.get('isLoading'), false, "no longer loading after promise is resolved");
  });
});

test('returns results when request is successful', function(assert) {
  let done = assert.async();
  assert.expect(1);

  let request = () => RSVP.resolve('results');

  this.searchRequest.start({
    request,
    success(results) {
      assert.equal(results, 'results', 'returns results');
      done();
    }
  });
});

test('does not call success when canceled', function(assert) {
  assert.expect(1);

  let request = () => RSVP.resolve('results');
  let successCallCount = 0;

  this.searchRequest.start({
    request,
    success() { successCallCount++; }
  });
  this.searchRequest.cancel();

  return wait().then(() => {
    assert.equal(successCallCount, 0, 'success was not called');
  });
});

test('callback is debounced', function(assert) {
  assert.expect(1);

  let callCount = 0;
  let request = () => {
    callCount++;
    return RSVP.resolve();
  };

  this.searchRequest.start({ request });
  this.searchRequest.start({ request });
  this.searchRequest.start({ request });

  return wait().then(() => {
    assert.equal(callCount, 1, 'callback only called once');
  });
});

test('does not set isLoading or isWaiting to false when restarted', function(assert) {
  assert.expect(4);
  let done1 = assert.async();
  let done2 = assert.async();

  let request1 = () => resolveAfter(10);
  let request2 = () => resolveAfter(20);

  this.searchRequest.start({
    request: request1,
    delayResults: 10,
    complete: () => {
      assert.equal(this.searchRequest.get('isLoading'), true, 'is still loading after first request resolves');
      assert.equal(this.searchRequest.get('isWaiting'), true, 'is still waiting after first request resolves');
      done1();
    }
  });

  this.searchRequest.start({
    request: request2,
    delayResults: 10,
    complete: () => {
      assert.equal(this.searchRequest.get('isLoading'), false, 'is not loading after second request resolves');
      assert.equal(this.searchRequest.get('isWaiting'), false, 'is not waiting after second request resolves');
      done2();
    }
  });
});
