RSpec.describe Artemisia::Managers::Component do
  Given(:manager) { described_class.new }
  Given(:entity) { build(:entity) }
  Given(:entity_id) { entity.id }

  describe '#initialize' do
    Then { manager.components.empty? }
  end

  describe '#add_component' do
    Given(:component) { build(:disabled) }
    Given { allow(EventBus).to receive(:announce) }

    When { manager.add_component(entity_id, component) }

    Then { manager.components[component.class].keys.include?(entity_id) }

    # rubocop:disable Layout/LineLength
    Then { expect(EventBus).to have_received(:announce).with(:component_added_to_entity, entity_id: entity_id, component: component) }
    # rubocop:enable Layout/LineLength
  end

  describe '#remove_component' do
    Given(:component) { build(:disabled) }

    Given { allow(EventBus).to receive(:announce) }
    Given { manager.add_component(entity_id, component) }

    When { manager.remove_component(entity_id, component) }

    Then { !manager.components[component.class].keys.include?(entity_id) }

    # rubocop:disable Layout/LineLength
    Then { expect(EventBus).to have_received(:announce).with(:component_removed_from_entity, entity_id: entity_id, component: component) }
    # rubocop:enable Layout/LineLength
  end

  describe '#component' do
    subject { super().component(entity_id, component_type) }

    Given(:component) { build(:disabled) }
    Given(:component_type) { component.class }

    When(:component_found) { manager.component(entity_id, component_type) }

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

      Then { component_found.nil? }
    end

    context 'known entity' do
      context 'known component type' do
        Given { manager.add_component(entity_id, component) }

        Then { component_found == component }
      end

      context 'unknown component type' do
        Given(:component_type) { Hash }

        Then { component_found.nil? }
      end
    end
  end

  describe '#all_components' do
    Given(:entity1_id) { 'abc' }
    Given(:entity2_id) { 'xyz' }
    Given(:component1) { build(:disabled) }
    Given(:component2) { build(:hidden) }

    Given do
      manager.add_component(entity1_id, component1)
      manager.add_component(entity2_id, component2)
    end

    When(:all_locations) { manager.all_components(component_type) }

    context 'unknown component type' do
      Given(:component_type) { Hash }

      Then { expect(all_locations).to eq([]) }
    end

    context 'known component type' do
      Given(:component_type) { Artemisia::Components::Hidden }

      Then { expect(all_locations).to match([component2]) }
    end
  end
end
