require 'rails_helper'
require "cancan/matchers"

describe Ability do
  subject { ability }

  let(:ability) { described_class.new(current_user) }
  let(:open_multi_volume_work) {
    FactoryGirl.build(:multi_volume_work,
                      user: creating_user,
                      state: 'complete')
  }
  let(:open_scanned_resource) {
    FactoryGirl.build(:open_scanned_resource,
                      user: creating_user,
                      state: 'complete')
  }
  let(:private_scanned_resource) {
    FactoryGirl.build(:private_scanned_resource,
                      user: creating_user,
                      state: 'complete')
  }
  let(:campus_only_scanned_resource) {
    FactoryGirl.build(:campus_only_scanned_resource,
                      user: creating_user,
                      state: 'complete')
  }
  let(:pending_scanned_resource) {
    FactoryGirl.build(:scanned_resource,
                      user: creating_user,
                      state: 'pending')
  }
  let(:metadata_review_scanned_resource) {
    FactoryGirl.build(:scanned_resource,
                      user: creating_user,
                      state: 'metadata_review')
  }
  let(:final_review_scanned_resource) {
    FactoryGirl.build(:scanned_resource,
                      user: creating_user,
                      state: 'final_review')
  }
  let(:complete_scanned_resource) {
    FactoryGirl.build(:scanned_resource,
                      user: image_editor,
                      state: 'complete',
                      identifier: 'ark:/99999/fk4445wg45')
  }
  let(:takedown_scanned_resource) {
    FactoryGirl.build(:scanned_resource,
                      user: image_editor,
                      state: 'takedown',
                      identifier: 'ark:/99999/fk4445wg45')
  }
  let(:flagged_scanned_resource) {
    FactoryGirl.build(:scanned_resource,
                      user: image_editor,
                      state: 'flagged',
                      identifier: 'ark:/99999/fk4445wg45')
  }
  let(:image_editor_file) {
    FactoryGirl.build(:file_set, user: image_editor)
  }
  let(:admin_file) { FactoryGirl.build(:file_set, user: admin_user) }
  let(:admin_user) { FactoryGirl.create(:admin) }
  let(:image_editor) { FactoryGirl.create(:image_editor) }
  let(:editor) { FactoryGirl.create(:editor) }
  let(:fulfiller) { FactoryGirl.create(:fulfiller) }
  let(:curator) { FactoryGirl.create(:curator) }
  let(:campus_user) { FactoryGirl.create(:user) }
  let(:role) { Role.where(name: 'admin').first_or_create }
  let(:solr) { ActiveFedora.solr.conn }

  before do
    allow(open_scanned_resource).to receive(:id).and_return("open")
    allow(private_scanned_resource).to receive(:id).and_return("private")
    allow(campus_only_scanned_resource).to receive(:id) \
      .and_return("campus_only")
    allow(pending_scanned_resource).to receive(:id).and_return("pending")
    allow(metadata_review_scanned_resource).to receive(:id) \
      .and_return("metadata_review")
    allow(final_review_scanned_resource).to receive(:id) \
      .and_return("final_review")
    allow(complete_scanned_resource).to receive(:id).and_return("complete")
    allow(takedown_scanned_resource).to receive(:id).and_return("takedown")
    allow(flagged_scanned_resource).to receive(:id).and_return("flagged")
    allow(image_editor_file).to receive(:id).and_return("image_editor_file")
    allow(admin_file).to receive(:id).and_return("admin_file")
    [
      open_scanned_resource,
      private_scanned_resource,
      campus_only_scanned_resource,
      pending_scanned_resource,
      metadata_review_scanned_resource,
      final_review_scanned_resource,
      complete_scanned_resource,
      takedown_scanned_resource,
      flagged_scanned_resource,
      image_editor_file,
      admin_file
    ].each do |obj|
      allow(ability.cache).to receive(:get) \
        .with(obj.id) \
        .and_return(Hydra::PermissionsSolrDocument.new(obj.to_solr, nil))
    end
  end

  describe 'as an admin' do
    let(:admin_user) { FactoryGirl.create(:admin) }
    let(:creating_user) { image_editor }
    let(:current_user) { admin_user }
    let(:open_scanned_resource_presenter) {
      ScannedResourceShowPresenter.new(open_scanned_resource, ability)
    }

    it {
      is_expected.to be_able_to(:create, ScannedResource.new)
      is_expected.to be_able_to(:create, FileSet.new)
      is_expected.to be_able_to(:read, open_scanned_resource)
      is_expected.to be_able_to(:read, private_scanned_resource)
      is_expected.to be_able_to(:read, takedown_scanned_resource)
      is_expected.to be_able_to(:read, flagged_scanned_resource)
      is_expected.to be_able_to(:pdf, open_scanned_resource)
      is_expected.to be_able_to(:color_pdf, open_scanned_resource)
    }
    it {
      is_expected.to be_able_to(:edit, open_scanned_resource)
      is_expected.to be_able_to(:edit, open_scanned_resource_presenter.id)
      is_expected.to be_able_to(:edit, private_scanned_resource)
      is_expected.to be_able_to(:edit, takedown_scanned_resource)
      is_expected.to be_able_to(:edit, flagged_scanned_resource)
      is_expected.to be_able_to(:file_manager, open_scanned_resource)
      is_expected.to be_able_to(:file_manager, open_multi_volume_work)
      is_expected.to be_able_to(:update, open_scanned_resource)
    }
    it {
      is_expected.to be_able_to(:update, private_scanned_resource)
      is_expected.to be_able_to(:update, takedown_scanned_resource)
      is_expected.to be_able_to(:update, flagged_scanned_resource)
      is_expected.to be_able_to(:destroy, open_scanned_resource)
      is_expected.to be_able_to(:destroy, private_scanned_resource)
      is_expected.to be_able_to(:destroy, takedown_scanned_resource)
      is_expected.to be_able_to(:destroy, flagged_scanned_resource)
      is_expected.to be_able_to(:manifest, open_scanned_resource)
    }
    it {
      is_expected.to be_able_to(:manifest, pending_scanned_resource)
    }
  end

  describe 'as an image editor' do
    let(:creating_user) { image_editor }
    let(:current_user) { image_editor }

    it {
      is_expected.to be_able_to(:read, open_scanned_resource)
      is_expected.to be_able_to(:manifest, open_scanned_resource)
      is_expected.not_to be_able_to(:pdf, open_scanned_resource)
      is_expected.not_to be_able_to(:color_pdf, open_scanned_resource)
      is_expected.to be_able_to(:flag, open_scanned_resource)
      is_expected.to be_able_to(:read, campus_only_scanned_resource)
      is_expected.to be_able_to(:read, private_scanned_resource)
      is_expected.to be_able_to(:read, pending_scanned_resource)
    }
    it {
      is_expected.to be_able_to(:read, metadata_review_scanned_resource)
      is_expected.to be_able_to(:read, final_review_scanned_resource)
      is_expected.to be_able_to(:read, complete_scanned_resource)
      is_expected.to be_able_to(:read, takedown_scanned_resource)
      is_expected.to be_able_to(:read, flagged_scanned_resource)
      is_expected.to be_able_to(:download, image_editor_file)
      is_expected.to be_able_to(:file_manager, open_scanned_resource)
      is_expected.to be_able_to(:file_manager, open_multi_volume_work)
    }
    it {
      is_expected.to be_able_to(:save_structure, open_scanned_resource)
      is_expected.to be_able_to(:update, open_scanned_resource)
      is_expected.to be_able_to(:create, ScannedResource.new)
      is_expected.to be_able_to(:create, FileSet.new)
      is_expected.to be_able_to(:destroy, image_editor_file)
      is_expected.to be_able_to(:destroy, pending_scanned_resource)
      is_expected.not_to be_able_to(:create, Role.new)
      is_expected.not_to be_able_to(:destroy, role)
    }
    it {
      is_expected.not_to be_able_to(:complete, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, complete_scanned_resource)
      is_expected.not_to be_able_to(:destroy, admin_file)
    }
  end

  describe 'as an editor' do
    let(:creating_user) { image_editor }
    let(:current_user) { editor }

    it {
      is_expected.to be_able_to(:read, open_scanned_resource)
      is_expected.to be_able_to(:read, campus_only_scanned_resource)
      is_expected.to be_able_to(:read, private_scanned_resource)
      is_expected.to be_able_to(:read, pending_scanned_resource)
      is_expected.to be_able_to(:read, metadata_review_scanned_resource)
      is_expected.to be_able_to(:read, final_review_scanned_resource)
      is_expected.to be_able_to(:read, complete_scanned_resource)
      is_expected.to be_able_to(:read, takedown_scanned_resource)
    }
    it {
      is_expected.to be_able_to(:read, flagged_scanned_resource)
      is_expected.to be_able_to(:manifest, open_scanned_resource)
      is_expected.not_to be_able_to(:pdf, open_scanned_resource)
      is_expected.not_to be_able_to(:color_pdf, open_scanned_resource)
      is_expected.to be_able_to(:flag, open_scanned_resource)
      is_expected.to be_able_to(:flag, private_scanned_resource)
      is_expected.to be_able_to(:file_manager, open_scanned_resource)
      is_expected.to be_able_to(:file_manager, open_multi_volume_work)
    }
    it {
      is_expected.to be_able_to(:save_structure, open_scanned_resource)
      is_expected.to be_able_to(:update, open_scanned_resource)
      is_expected.not_to be_able_to(:download, image_editor_file)
      is_expected.not_to be_able_to(:create, ScannedResource.new)
      is_expected.not_to be_able_to(:create, FileSet.new)
      is_expected.not_to be_able_to(:destroy, image_editor_file)
      is_expected.not_to be_able_to(:destroy, pending_scanned_resource)
      is_expected.not_to be_able_to(:create, Role.new)
    }
    it {
      is_expected.not_to be_able_to(:destroy, role)
      is_expected.not_to be_able_to(:complete, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, complete_scanned_resource)
      is_expected.not_to be_able_to(:destroy, admin_file)
    }
  end

  describe 'as a fulfiller' do
    let(:creating_user) { image_editor }
    let(:current_user) { fulfiller }

    it {
      is_expected.to be_able_to(:read, open_scanned_resource)
      is_expected.to be_able_to(:read, campus_only_scanned_resource)
      is_expected.to be_able_to(:read, private_scanned_resource)
      is_expected.to be_able_to(:read, pending_scanned_resource)
      is_expected.to be_able_to(:read, metadata_review_scanned_resource)
      is_expected.to be_able_to(:read, final_review_scanned_resource)
      is_expected.to be_able_to(:read, complete_scanned_resource)
      is_expected.to be_able_to(:read, takedown_scanned_resource)
    }
    it {
      is_expected.to be_able_to(:read, flagged_scanned_resource)
      is_expected.to be_able_to(:manifest, open_scanned_resource)
      is_expected.not_to be_able_to(:pdf, open_scanned_resource)
      is_expected.to be_able_to(:flag, open_scanned_resource)
      is_expected.to be_able_to(:flag, private_scanned_resource)
      is_expected.to be_able_to(:download, image_editor_file)
    }
    it {
      is_expected.not_to be_able_to(:file_manager, open_scanned_resource)
      is_expected.not_to be_able_to(:file_manager, open_multi_volume_work)
      is_expected.not_to be_able_to(:save_structure, open_scanned_resource)
      is_expected.not_to be_able_to(:update, open_scanned_resource)
      is_expected.not_to be_able_to(:create, ScannedResource.new)
      is_expected.not_to be_able_to(:create, FileSet.new)
      is_expected.not_to be_able_to(:destroy, image_editor_file)
      is_expected.not_to be_able_to(:destroy, pending_scanned_resource)
    }
    it {
      is_expected.not_to be_able_to(:create, Role.new)
      is_expected.not_to be_able_to(:destroy, role)
      is_expected.not_to be_able_to(:complete, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, complete_scanned_resource)
      is_expected.not_to be_able_to(:destroy, admin_file)
    }
  end

  describe 'as a curator' do
    let(:creating_user) { image_editor }
    let(:current_user) { curator }

    it {
      is_expected.to be_able_to(:read, open_scanned_resource)
      is_expected.to be_able_to(:read, campus_only_scanned_resource)
      is_expected.to be_able_to(:read, private_scanned_resource)
      is_expected.to be_able_to(:read, metadata_review_scanned_resource)
      is_expected.to be_able_to(:read, final_review_scanned_resource)
      is_expected.to be_able_to(:read, complete_scanned_resource)
      is_expected.to be_able_to(:read, takedown_scanned_resource)
      is_expected.to be_able_to(:read, flagged_scanned_resource)
    }
    it {
      is_expected.to be_able_to(:manifest, open_scanned_resource)
      is_expected.not_to be_able_to(:pdf, open_scanned_resource)
      is_expected.to be_able_to(:flag, open_scanned_resource)
      is_expected.not_to be_able_to(:read, pending_scanned_resource)
      is_expected.not_to be_able_to(:download, image_editor_file)
      is_expected.not_to be_able_to(:file_manager, open_scanned_resource)
      is_expected.not_to be_able_to(:file_manager, open_multi_volume_work)
      is_expected.not_to be_able_to(:save_structure, open_scanned_resource)
    }
    it {
      is_expected.not_to be_able_to(:update, open_scanned_resource)
      is_expected.not_to be_able_to(:create, ScannedResource.new)
      is_expected.not_to be_able_to(:create, FileSet.new)
      is_expected.not_to be_able_to(:destroy, image_editor_file)
      is_expected.not_to be_able_to(:destroy, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, complete_scanned_resource)
      is_expected.not_to be_able_to(:create, Role.new)
      is_expected.not_to be_able_to(:destroy, role)
    }
    it {
      is_expected.not_to be_able_to(:complete, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, admin_file)
    }
  end

  describe 'as a campus user' do
    let(:creating_user) { FactoryGirl.create(:image_editor) }
    let(:current_user) { campus_user }

    it {
      is_expected.to be_able_to(:read, open_scanned_resource)
      is_expected.to be_able_to(:read, campus_only_scanned_resource)
      is_expected.to be_able_to(:read, complete_scanned_resource)
      is_expected.to be_able_to(:read, flagged_scanned_resource)
      is_expected.to be_able_to(:manifest, open_scanned_resource)
      is_expected.to be_able_to(:manifest, campus_only_scanned_resource)
      is_expected.to be_able_to(:manifest, complete_scanned_resource)
      is_expected.to be_able_to(:manifest, flagged_scanned_resource)
    }
    it {
      is_expected.not_to be_able_to(:pdf, open_scanned_resource)
      is_expected.not_to be_able_to(:pdf, campus_only_scanned_resource)
      is_expected.not_to be_able_to(:pdf, complete_scanned_resource)
      is_expected.not_to be_able_to(:pdf, flagged_scanned_resource)
      is_expected.to be_able_to(:flag, open_scanned_resource)
      is_expected.to be_able_to(:flag, campus_only_scanned_resource)
      is_expected.to be_able_to(:flag, complete_scanned_resource)
    }
    it {
      is_expected.not_to be_able_to(:read, private_scanned_resource)
      is_expected.not_to be_able_to(:read, pending_scanned_resource)
      is_expected.not_to be_able_to(:read, metadata_review_scanned_resource)
      is_expected.not_to be_able_to(:read, final_review_scanned_resource)
      is_expected.not_to be_able_to(:read, takedown_scanned_resource)
      is_expected.not_to be_able_to(:download, image_editor_file)
      is_expected.not_to be_able_to(:file_manager, open_scanned_resource)
      is_expected.not_to be_able_to(:file_manager, open_multi_volume_work)
    }
    it {
      is_expected.not_to be_able_to(:save_structure, open_scanned_resource)
      is_expected.not_to be_able_to(:update, open_scanned_resource)
      is_expected.not_to be_able_to(:create, ScannedResource.new)
      is_expected.not_to be_able_to(:create, FileSet.new)
      is_expected.not_to be_able_to(:destroy, image_editor_file)
      is_expected.not_to be_able_to(:destroy, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, complete_scanned_resource)
      is_expected.not_to be_able_to(:create, Role.new)
    }
    it {
      is_expected.not_to be_able_to(:destroy, role)
      is_expected.not_to be_able_to(:complete, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, admin_file)
    }
  end

  describe 'as an anonymous user' do
    let(:creating_user) { FactoryGirl.create(:image_editor) }
    let(:current_user) { nil }
    let(:color_enabled_resource) {
      FactoryGirl.build(:open_scanned_resource,
                        user: creating_user,
                        state: 'complete',
                        pdf_type: ['color'])
    }
    let(:no_pdf_scanned_resource) {
      FactoryGirl.build(:open_scanned_resource,
                        user: creating_user,
                        state: 'complete',
                        pdf_type: [])
    }

    it {
      is_expected.to be_able_to(:read, open_scanned_resource)
      is_expected.to be_able_to(:manifest, open_scanned_resource)
      is_expected.not_to be_able_to(:pdf, open_scanned_resource)
      is_expected.to be_able_to(:read, complete_scanned_resource)
      is_expected.to be_able_to(:manifest, complete_scanned_resource)
      is_expected.to be_able_to(:read, flagged_scanned_resource)
      is_expected.to be_able_to(:manifest, flagged_scanned_resource)
      is_expected.not_to be_able_to(:color_pdf, color_enabled_resource)
    }
    it {
      is_expected.not_to be_able_to(:pdf, no_pdf_scanned_resource)
      is_expected.not_to be_able_to(:flag, open_scanned_resource)
      is_expected.not_to be_able_to(:read, campus_only_scanned_resource)
      is_expected.not_to be_able_to(:read, private_scanned_resource)
      is_expected.not_to be_able_to(:read, pending_scanned_resource)
      is_expected.not_to be_able_to(:read, metadata_review_scanned_resource)
      is_expected.not_to be_able_to(:read, final_review_scanned_resource)
      is_expected.not_to be_able_to(:read, takedown_scanned_resource)
    }
    it {
      is_expected.not_to be_able_to(:download, image_editor_file)
      is_expected.not_to be_able_to(:file_manager, open_scanned_resource)
      is_expected.not_to be_able_to(:file_manager, open_multi_volume_work)
      is_expected.not_to be_able_to(:save_structure, open_scanned_resource)
      is_expected.not_to be_able_to(:update, open_scanned_resource)
      is_expected.not_to be_able_to(:create, ScannedResource.new)
      is_expected.not_to be_able_to(:create, FileSet.new)
      is_expected.not_to be_able_to(:destroy, image_editor_file)
    }
    it {
      is_expected.not_to be_able_to(:destroy, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, complete_scanned_resource)
      is_expected.not_to be_able_to(:create, Role.new)
      is_expected.not_to be_able_to(:destroy, role)
      is_expected.not_to be_able_to(:complete, pending_scanned_resource)
      is_expected.not_to be_able_to(:destroy, admin_file)
    }
  end
end
