RSpec.describe Artemisia::Managers::GroupManager do
  Given(:manager) { described_class.new }

  Given(:vilains) { :vilains }
  Given(:evils) { :evils }
  Given(:super_macho) { { name: 'super_macho' } }
  Given(:nefario) { { name: 'nefario' } }

  describe '#initialize' do
    Then { manager.group_entities.empty? }
    And { manager.entity_groups.empty? }
  end

  describe '#add' do
    Given { allow(EventBus).to receive(:announce) }

    When(:add) { manager.add(super_macho, vilains) }

    Then { manager.group_entities.count == 1 }
    And { manager.group_entities[vilains].include?(super_macho) }
    And { manager.entity_groups[super_macho].include?(vilains) }
    # rubocop:disable Layout/LineLength
    And { expect(EventBus).to have_received(:announce).with(:entity_added_to_group, entity_id: super_macho, group: vilains) }
    # rubocop:enable Layout/LineLength
  end

  describe '#remove' do
    Given { manager.add(super_macho, vilains) }
    Given { allow(EventBus).to receive(:announce) }

    When(:remove) { manager.remove(super_macho, vilains) }

    Then { manager.group_entities[vilains].empty? }
    And { manager.entity_groups[super_macho].empty? }
    # rubocop:disable Layout/LineLength
    And { expect(EventBus).to have_received(:announce).with(:entity_removed_from_group, entity_id: super_macho, group: vilains) }
    # rubocop:enable Layout/LineLength
  end

  describe '#remove_from_groups' do
    Given { manager.add(super_macho, vilains) }
    Given { manager.add(super_macho, evils) }

    When(:remove_from_groups) { manager.remove_from_groups(super_macho) }

    Then { !manager.group_entities[vilains].include?(super_macho) }
    And { !manager.group_entities[evils].include?(super_macho) }
  end

  describe '#entities' do
    When(:entities) { manager.entities(group) }

    context 'known group' do
      Given(:group) { vilains }

      Given { manager.add(super_macho, vilains) }
      Given { manager.add(nefario, vilains) }

      Then { entities == [super_macho, nefario] }
    end

    context 'unknown group' do
      Given(:group) { :unknown }

      Then { entities == [] }
    end
  end

  describe '#groups' do
    When(:groups) { manager.groups(entity) }

    context 'known group' do
      Given(:entity) { super_macho }

      Given { manager.add(super_macho, vilains) }
      Given { manager.add(super_macho, evils) }

      Then { groups == [vilains, evils] }
    end

    context 'unknown group' do
      Given(:entity) { :minions }

      Then { groups == [] }
    end
  end

  describe '#any_group?' do
    When(:any) { manager.any_group?(entity) }

    context 'known entity' do
      Given(:entity) { super_macho }

      Given { manager.add(super_macho, vilains) }

      Then { any == true }
    end

    context 'unknown entity' do
      Given(:entity) { 'unknown' }

      Then { any == false }
    end
  end

  describe '#in_group?' do
    When(:in_group) { manager.in_group?(entity, group) }

    Given(:group) { vilains }

    context 'known entity' do
      Given(:entity) { super_macho }

      Given { manager.add(super_macho, vilains) }

      Then { in_group == true }
    end

    context 'unknown entity' do
      Given(:entity) { 'unknown' }

      Then { in_group == false }
    end
  end
end
