import Ember from 'ember';
import { moduleFor, test } from 'ember-qunit';
const { run } = Ember;

moduleFor('service:community', 'community-service', {
  integration: true
});

test('identifies valid names', function (assert) {
  assert.expect(4);
  let service = this.subject();
  assert.ok(service.isValidName('one'), 'accepts alphabetic names');
  assert.ok(service.isValidName('one2'), 'accepts alphanumeric names');
  assert.ok(service.isValidName('one_two'), 'accepts underscores within names');
  assert.ok(service.isValidName('20one'), 'accepts names starting with numbers');
});

test('identifies invalid names', function (assert) {
  assert.expect(4);
  let service = this.subject();
  assert.ok(!service.isValidName('12'), 'does not accept numeric under 2 characters');
  assert.ok(!service.isValidName('a'), 'does not accept alphabetic names under 2 characters');
  assert.ok(!service.isValidName('y!ss'), 'does not accept names with special characters');
  // Bad test, requires state, should mock out BANNED_COMMUNITIES
  assert.ok(!service.isValidName('creative'), 'does not accept banned names');
});

test('returns a community tag', function (assert) {
  assert.expect(1);
  let service = this.subject();
  let tag = 'bar';
  run(() => {
    let model = service.tagToCommunity(tag);
    assert.equal(model.get('name'), tag);
  });
});

test('returns null when tag is invalid', function (assert) {
  assert.expect(1);
  let service = this.subject();
  let tag = '1';
  run(() => {
    let model = service.tagToCommunity(tag);
    assert.equal(model, null);
  });
});

test('identifies a tag', function (assert) {
  assert.expect(1);
  let service = this.subject();
  let tag = 'foo';
  run(() => {
    let model = service.tagToCommunity(tag);
    assert.ok(service.hasCommunityTag(model, `Title is #${tag}`), 'finds single tag');
  });
});

test('identifies in many tags', function (assert) {
  assert.expect(1);
  let service = this.subject();
  let tag = 'foo';
  run(() => {
    let model = service.tagToCommunity(tag);
    assert.equal(service.hasCommunityTag(model, `Title is #bar #${tag}`), true, 'finds a tag in many');
  });
});

test('identifies no tags', function (assert) {
  assert.expect(1);
  let service = this.subject();
  run(() => {
    let model = service.tagToCommunity('foo');
    assert.equal(service.hasCommunityTag(model, 'cat bear'), false, 'returns false without a tag');
  });
});

test('identifies a tag', function (assert) {
  assert.expect(2);
  let service = this.subject();
  let tag = 'foo';
  run(() => {
    let tags = service.extractFromTags(`#${tag}`);
    assert.equal(tags.length, 1, 'finds a single tag');
    assert.deepEqual(tags.mapBy('name'), [tag], 'returns an array of models with the tag');
  });
});

test('identifies many tags', function (assert) {
  assert.expect(2);
  let service = this.subject();
  let tagA = 'foo';
  let tagB = 'baz';
  run(() => {
    let tags = service.extractFromTags(`#${tagA} some text #${tagB}`);
    assert.equal(tags.length, 2, 'finds two tags');
    assert.deepEqual(tags.mapBy('name'), [tagA, tagB], 'returns array of models with tags');
  });
});

test('identifies no tags', function (assert) {
  assert.expect(1);
  let service = this.subject();
  let tags = service.extractFromTags(`some text # no tags`);
  assert.equal(tags.length, 0, 'finds no tags');
});

test('extract tag extracts tags that meet name validation', function (assert) {
  assert.expect(13);
  let service = this.subject();
  let tagOne = 'one';
  let tagTwo = 'two';
  let tagOneTwo = 'one_two';
  run(() => {
    assert.deepEqual(service.extractFromTags('').mapBy('name'), []);
    assert.deepEqual(service.extractFromTags('#one #two').mapBy('name'), [tagOne, tagTwo]);
    assert.deepEqual(service.extractFromTags('#one #two #one').mapBy('name'), [tagOne, tagTwo]);
    assert.deepEqual(service.extractFromTags('#one#two').mapBy('name'), [tagOne, tagTwo]);
    assert.deepEqual(service.extractFromTags('#one,#two').mapBy('name'), [tagOne, tagTwo]);
    assert.deepEqual(service.extractFromTags('#one ,#two').mapBy('name'), [tagOne, tagTwo]);
    assert.deepEqual(service.extractFromTags('#one;').mapBy('name'), [tagOne]);
    assert.deepEqual(service.extractFromTags('#one;#two').mapBy('name'), [tagOne, tagTwo]);
    assert.deepEqual(service.extractFromTags('#one!').mapBy('name'), [tagOne]);
    assert.deepEqual(service.extractFromTags('#one!#two').mapBy('name'), [tagOne, tagTwo]);
    assert.deepEqual(service.extractFromTags('#one_two').mapBy('name'), [tagOneTwo]);
    assert.deepEqual(service.extractFromTags('#one-two').mapBy('name'), [tagOne]);
    assert.deepEqual(service.extractFromTags('let\'s cook some #one and make it #two').mapBy('name'), [tagOne, tagTwo]);
  });
});

test('handles non-string being provided', function (assert) {
  assert.expect(5);
  let service = this.subject();
  assert.equal(service.extractFromTags().length, 0, 'finds no tags');
  assert.equal(service.extractFromTags(null).length, 0, 'finds no tags');
  assert.equal(service.extractFromTags(undefined).length, 0, 'finds no tags');
  assert.equal(service.extractFromTags([]).length, 0, 'finds no tags');
  assert.equal(service.extractFromTags({}).length, 0, 'finds no tags');
});
