#  Copyright (c) 2012-2018, Schweizer Blasmusikverband. This file is part of
#  hitobito_sbv and licensed under the Affero General Public License version 3
#  or later. See the COPYING file at the top-level directory or at
#  https://github.com/hitobito/hitobito.

require 'spec_helper'

describe TagList do

  let(:leader) { people(:top_leader) }
  let(:bottom_member) { people(:bottom_member) }
  let(:tag1) { ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('No mail') }
  let(:tag2) { ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('Category: Value') }

  context 'add tags' do
    it 'creates only one tag for one person' do
      tag_list = TagList.new([leader], [tag1])
      expect do
        expect(tag_list.add).to be 1
      end.to change { leader.tags.count }.by(1)
    end

    it 'does nothing if the tag already exists' do
      leader.tag_list.add(tag1)
      leader.save!
      tag_list = TagList.new([leader], [tag1])
      expect do
        expect(tag_list.add).to be 0
      end.not_to(change { leader.reload.tags.count })
    end

    it 'may create the same tag on multiple people' do
      tag_list = TagList.new([leader, bottom_member], [tag1])
      expect do
        expect(tag_list.add).to be 2
      end.to change { leader.tags.count }.by(1).and change { bottom_member.tags.count }.by(1)

      expect(leader.reload.tags.collect(&:name)).to include tag1.name
      expect(bottom_member.reload.tags.collect(&:name)).to include tag1.name
    end

    it 'may create multiple tags for one person' do
      tag_list = TagList.new([leader], [tag1, tag2])
      expect do
        expect(tag_list.add).to be 2
      end.to change { leader.tags.count }.by(2)

      expect(leader.reload.tags.collect(&:name)).to include tag1.name, tag2.name
    end

    it 'may create multiple tags on multiple people' do
      bottom_member.tag_list.add(tag2)
      bottom_member.save!
      tag_list = TagList.new([leader, bottom_member], [tag1, tag2])
      expect do
        expect(tag_list.add).to be 3
      end.to change { leader.tags.count }.by(2).and change { bottom_member.tags.count }.by(1)

      expect(leader.reload.tags.collect(&:name)).to include tag1.name, tag2.name
      expect(bottom_member.reload.tags.collect(&:name)).to include tag1.name, tag2.name
    end
  end

  context 'remove tags' do
    it 'deletes only one tag from one person' do
      leader.tag_list.add(tag1)
      leader.save!
      tag_list = TagList.new([leader], [tag1])
      expect do
        expect(tag_list.remove).to be 1
      end.to change { leader.tags.count }.by(-1)
    end

    it 'does nothing if the tag does not exist on the person' do
      tag_list = TagList.new([leader], [tag1])
      expect do
        expect(tag_list.remove).to be 0
      end.not_to(change { leader.reload.tags.count })
    end

    it 'may delete the same tag from multiple people' do
      leader.tag_list.add(tag1)
      leader.save!
      bottom_member.tag_list.add(tag1)
      bottom_member.save!
      tag_list = TagList.new([leader, bottom_member], [tag1])
      expect do
        expect(tag_list.remove).to be 2
      end.to change { leader.tags.count }.by(-1).and change { bottom_member.tags.count }.by(-1)

      expect(leader.reload.tags.collect(&:name)).not_to include tag1.name
      expect(bottom_member.reload.tags.collect(&:name)).not_to include tag1.name
    end

    it 'may delete multiple tags from one person' do
      leader.tag_list.add(tag1, tag2)
      leader.save!
      tag_list = TagList.new([leader], [tag1, tag2])
      expect do
        expect(tag_list.remove).to be 2
      end.to change { leader.tags.count }.by(-2)

      expect(leader.reload.tags.collect(&:name)).not_to include tag1.name, tag2.name
    end

    it 'may delete multiple tags from multiple people' do
      leader.tag_list.add(tag1, tag2)
      leader.save!
      bottom_member.tag_list.add(tag1)
      bottom_member.save!
      tag_list = TagList.new([leader, bottom_member], [tag1, tag2])
      expect do
        expect(tag_list.remove).to be 3
      end.to change { leader.tags.count }.by(-2).and change { bottom_member.tags.count }.by(-1)

      expect(leader.reload.tags.collect(&:name)).not_to include tag1.name, tag2.name
      expect(bottom_member.reload.tags.collect(&:name)).not_to include tag1.name, tag2.name
    end
  end

end
