import { moduleFor, test } from 'ember-qunit';
import wait from 'ember-test-helpers/wait';
import followScenario from 'web-client/mirage/scenarios/follow';
import run from 'ember-runloop';
import {
  setup as setupMirage, teardown as teardownMirage
} from 'web-client/tests/helpers/setup-mirage-for-integration';

moduleFor('service:paginator', 'Integration | Service | paginator', {
  integration: true,
  beforeEach() {
    this.store = this.container.lookup('service:store');
    setupMirage(this);
  },
  afterEach() {
    teardownMirage(this);
  }
});

test('#paginatorFor returns a new page; can fetch pages', function(assert) {
  assert.expect(6);

  let id = 'twitch';
  let channel = run(() => this.store.push({
    data: {
      id,
      type: 'channel',
      relationships: {
        following: {
          links: {
            related: `/kraken/users/${id}/follows/channels?offset=0&on_site=1`
          }
        }
      }
    }
  }));

  for (let i = 0; i < 60; i++) {
    followScenario(this.server, { name: `follow${i}`});
  }

  let paginator = this.subject();
  let page = paginator.paginatorFor({
    model: channel,
    relationshipName: 'following',
    pageFactory: 'follow'
  });

  assert.equal(page.get('items.length'), 0, 'initial items length 0');
  assert.equal(page.get('total'), 0, 'initial total is 0');
  page.fetchNextPage();
  return wait().then(() => {
    assert.equal(page.get('items.length'), 25, 'items length 25 after first page');
    assert.equal(page.get('total'), 60, 'total set from meta');

    page.fetchNextPage();
    return wait();
  }).then(() => {
    assert.equal(page.get('items.length'), 50, 'items length 50 after second page');
    assert.equal(page.get('total'), 60, 'total set from meta');
  });
});

test('#paginatorFor when called with a feed, returns pages of posts', function(assert) {
  assert.expect(12);

  let feed = run(() => this.store.push({
    data: { id: '1', type: 'feed' }
  }));

  let paginator = this.subject();
  let page = paginator.paginatorFor({
    model: feed,
    relationshipName: 'allPosts',
    pageFactory: 'feed-post'
  });

  let posts = [];
  for (let i = 0; i < 20; i++) {
    posts.pushObject(this.server.create('post'));
  }

  let calledWithoutCursor = 0;
  let calledWithCursor = 0;
  let topic = 'topic?';
  this.server.get('http://api.twitch.tv/kraken/feed/:channel/posts', function(schema, request) {
    if (!request.queryParams.cursor) {
      calledWithoutCursor++;
      return {
        _cursor: 10,
        _total: 20,
        _topic: topic,
        posts: posts.slice(0, 10)
      };
    }

    assert.equal(request.queryParams.cursor, '10', 'cursor from previous request passed');
    calledWithCursor++;
    return {
      _cursor: 20,
      _total: 20,
      _topic: topic,
      posts: posts.slice(10, 20)
    };
  });

  assert.equal(page.get('items.length'), 0, 'initial items length 0');
  assert.equal(page.get('total'), 0, 'initial total is 0');
  page.fetchNextPage();
  return wait().then(() => {
    assert.equal(page.get('items.length'), 10, 'items length 10 after first page');
    assert.equal(page.get('total'), 20, 'total set from meta');
    assert.notOk(page.isComplete, 'not isComplete');
    page.fetchNextPage();
    return wait();
  }).then(() => {
    assert.equal(page.get('items.length'), 20, 'items length 20 after second page');
    assert.equal(page.get('total'), 20, 'total set from meta');
    assert.ok(page.isComplete, 'isComplete');

    assert.equal(calledWithoutCursor, 1, 'called once without cursor');
    assert.equal(calledWithCursor, 1, 'called once with cursor');
    assert.equal(page.topic, topic, 'topic set');
  });
});
