import Evented from 'ember-evented';
import EmberObject from 'ember-object';
import RSVP from 'rsvp';
import { moduleFor } from 'ember-qunit';
import test from 'ember-sinon-qunit/test-support/test';

moduleFor('service:whispers-pubsub');

const TEST_IM_MESSAGE = {
  id: 999,
  thread_id: '11111111_22222222',
  body: 'Kappa hello PogChamp',
  sent_ts: 1000000000,
  from_id: 11111111,
  tags: {
    badges: [{
      id: 'turbo',
      version: 1
    }, {
      id: 'alliance',
      version: 1
    }],
    login: 'from_user',
    display_name: 'FromUser',
    color: '#19B391',
    user_type: 'staff',
    turbo: true,
    emotes: [{
      id: 25,
      start: 0,
      end: 4
    }, {
      id: 88,
      start: 12,
      end: 19
    }]
  },
  recipient: {
    id: 22222222,
    username: 'to_user',
    display_name: 'ToUser',
    color: '',
    user_type: '',
    turbo: false
  },
  nonce: 'abcdefg'
};


let MockPubsub = EmberObject.extend(Evented, {
  Listen(obj) {
    this._listenCapture = obj;
  },

  _triggerMessage(message) {
    this._listenCapture.message(message);
  }
});

function newMockTwitchUser(id, chatOauthToken) {
  return RSVP.resolve({
    id: id,
    chat_oautth_token: chatOauthToken
  });
}

function setupMocks(service) {
  let mockPubsub = new MockPubsub();
  let mockTwitchUser = newMockTwitchUser(11111111, 'abcdefg');
  service._pubsub = () => { return mockPubsub; };
  service.session = {
    getCurrentUser() {
      return RSVP.resolve(mockTwitchUser);
    }
  };
}

test('it triggers a whisper event when pubsub emits whisper messages', function(assert) {
  // given
  let done = assert.async(2);
  assert.expect(2);

  let service = this.subject();
  setupMocks(service);

  // then
  service.on('whisper', () => {
    assert.ok(true, 'whisper triggered');
    done();
  });

  // when
  service.setupService().then(() => {
    let mockPubsub = service._pubsub();
    mockPubsub._triggerMessage(JSON.stringify({type: 'whisper_received', data_object: TEST_IM_MESSAGE}));
    mockPubsub._triggerMessage(JSON.stringify({type: 'whisper_sent', data_object: TEST_IM_MESSAGE}));
  });
});

test('it triggers a whisper event when pubsub emits a thread', function(assert) {
  // given
  let done = assert.async(1);
  assert.expect(1);

  let service = this.subject();
  setupMocks(service);

  // then
  service.on('thread', () => {
    assert.ok(true, 'thread triggered');
    done();
  });

  // when
  service.setupService().then(() => {
    let mockPubsub = service._pubsub();
    mockPubsub._triggerMessage(JSON.stringify({type: 'thread', data_object: {}}));
  });

});

test('it triggers a whisper event when pubsub emits threads', function(assert) {
  // given
  let done = assert.async(1);
  assert.expect(1);

  let service = this.subject();
  setupMocks(service);

  // then
  service.on('threads', () => {
    assert.ok(true, 'threads triggered');
    done();
  });

  // when
  service.setupService().then(() => {
    let mockPubsub = service._pubsub();
    mockPubsub._triggerMessage(JSON.stringify({type: 'threads', data_object: {}}));
  });

});

test('it triggers a reconnecting event when pubsub disconnects and then connects', function(assert) {
  // given
  let done = assert.async();
  assert.expect(1);

  let service = this.subject();
  setupMocks(service);

  // then
  service.on('reconnecting', () => {
    assert.ok(true, 'reconnecting triggered');
    done();
  });

  // when
  service.setupService().then(() => {
    let mockPubsub = service._pubsub();
    mockPubsub.trigger('disconnected');
    mockPubsub.trigger('connected');
  });
});
