require File.expand_path('../../../spec_helper', __FILE__)

module Pod
  describe UserProjectIntegrator = Installer::UserProjectIntegrator do

    describe "In general" do

      before do
        @sample_project_path = SpecHelper.create_sample_app_copy_from_fixture('SampleProject')
        sample_project_path = @sample_project_path
        @podfile = Podfile.new do
          platform :ios
          xcodeproj sample_project_path
          pod 'JSONKit'
          target :empty do

          end
        end
        config.sandbox.project = Project.new(config.sandbox.project_path)
        Xcodeproj::Project.new(config.sandbox.project_path).save
        @library = AggregateTarget.new(@podfile.target_definitions['Pods'], config.sandbox)
        @library.client_root = sample_project_path.dirname
        @library.user_project_path  = sample_project_path
        @library.user_target_uuids  = ['A346496C14F9BE9A0080D870']
        empty_library = AggregateTarget.new(@podfile.target_definitions[:empty], config.sandbox)
        @integrator = UserProjectIntegrator.new(@podfile, config.sandbox, temporary_directory, [@library, empty_library])
      end

      #-----------------------------------------------------------------------#

      describe "In general" do
        before do
          @integrator.stubs(:warn_about_xcconfig_overrides)
        end

        it "adds the Pods project to the workspace" do
          UserProjectIntegrator::TargetIntegrator.any_instance.stubs(:integrate!)
          @integrator.integrate!
          workspace_path = @integrator.send(:workspace_path)
          workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
          pods_project_ref = workspace.file_references.find do |ref|
            ref.path =~ /Pods.xcodeproj/
          end
          pods_project_ref.should.not.be.nil
        end

        it "integrates the user targets" do
          UserProjectIntegrator::TargetIntegrator.any_instance.expects(:integrate!)
          @integrator.integrate!
        end

        it "warns if the podfile does not contain any dependency" do
          Podfile::TargetDefinition.any_instance.stubs(:empty?).returns(true)
          @integrator.integrate!
          UI.warnings.should.include?('The Podfile does not contain any dependencies')
        end

        it 'check that the integrated target does not override the CocoaPods build settings' do
          UI.warnings = ''
          target_config = stub(:name => 'Release', :build_settings => { 'GCC_PREPROCESSOR_DEFINITIONS' => 'FLAG=1' })
          user_target = stub(:name => 'SampleProject', :build_configurations => [target_config])
          @library.stubs(:user_targets).returns([user_target])

          @library.xcconfigs['Release'] = {'GCC_PREPROCESSOR_DEFINITIONS' => 'COCOAPODS=1'}
          @integrator = UserProjectIntegrator.new(@podfile, config.sandbox, temporary_directory, [@library])

          @integrator.unstub(:warn_about_xcconfig_overrides)
          @integrator.send(:warn_about_xcconfig_overrides)
          UI.warnings.should.include 'The `SampleProject [Release]` target ' \
            'overrides the `GCC_PREPROCESSOR_DEFINITIONS` build setting'
        end

        it 'allows build settings which inherit the settings form the CocoaPods xcconfig' do
          UI.warnings = ''
          target_config = stub(:name => 'Release', :build_settings => { 'GCC_PREPROCESSOR_DEFINITIONS' => 'FLAG=1 $(inherited)' })
          user_target = stub(:name => 'SampleProject', :build_configurations => [target_config])
          @library.stubs(:user_targets).returns([user_target])

          @library.xcconfigs['Release'] = {'GCC_PREPROCESSOR_DEFINITIONS' => 'COCOAPODS=1'}
          @integrator = UserProjectIntegrator.new(@podfile, config.sandbox, temporary_directory, [@library])

          @integrator.unstub(:warn_about_xcconfig_overrides)
          @integrator.send(:warn_about_xcconfig_overrides)
          UI.warnings.should.not.include 'GCC_PREPROCESSOR_DEFINITIONS'
        end

      end

      #-----------------------------------------------------------------------#

      describe "Workspace creation" do

        it "creates a new workspace if needed" do
          @integrator.send(:create_workspace)
          workspace_path = @integrator.send(:workspace_path)
          saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
          saved.file_references.map(&:path).should == [
            "SampleProject/SampleProject.xcodeproj",
            "Pods/Pods.xcodeproj"
          ]
        end

        it "updates an existing workspace if needed" do
          workspace_path = @integrator.send(:workspace_path)
          ref = Xcodeproj::Workspace::FileReference.new('SampleProject/SampleProject.xcodeproj', 'group')
          workspace = Xcodeproj::Workspace.new(ref)
          workspace.save_as(workspace_path)
          @integrator.send(:create_workspace)
          saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
          saved.file_references.map(&:path).should == [
            "SampleProject/SampleProject.xcodeproj",
            "Pods/Pods.xcodeproj"
          ]
        end

        it "doesn't write the workspace if not needed" do
          file_references = [
            Xcodeproj::Workspace::FileReference.new('SampleProject/SampleProject.xcodeproj', 'group'),
            Xcodeproj::Workspace::FileReference.new('Pods/Pods.xcodeproj', 'group')
          ]

          workspace = Xcodeproj::Workspace.new(file_references)
          workspace_path = @integrator.send(:workspace_path)
          workspace.save_as(workspace_path)
          Xcodeproj::Workspace.expects(:save_as).never
          @integrator.send(:create_workspace)
        end

        it "only appends projects to the workspace and never deletes one" do
          ref = Xcodeproj::Workspace::FileReference.new('user_added_project.xcodeproj', 'group')
          workspace = Xcodeproj::Workspace.new(ref)
          workspace_path = @integrator.send(:workspace_path)
          workspace.save_as(workspace_path)
          @integrator.send(:create_workspace)
          saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
          saved.file_references.map(&:path).should == [
            'user_added_project.xcodeproj',
            "SampleProject/SampleProject.xcodeproj",
            "Pods/Pods.xcodeproj"
          ]
        end

        it "preserves the order of the projects in the workspace" do
          file_references = [
            Xcodeproj::Workspace::FileReference.new('Pods/Pods.xcodeproj', 'group'),
            Xcodeproj::Workspace::FileReference.new('SampleProject/SampleProject.xcodeproj', 'group'),
          ]

          workspace = Xcodeproj::Workspace.new(file_references)
          workspace_path = @integrator.send(:workspace_path)
          workspace.save_as(workspace_path)
          @integrator.send(:create_workspace)
          saved = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
          saved.file_references.map(&:path).should == [
            "Pods/Pods.xcodeproj",
            "SampleProject/SampleProject.xcodeproj",
          ]
        end

      end

      #-----------------------------------------------------------------------#

      describe "Private Helpers" do

        it "uses the path of the workspace defined in the podfile" do
          path = "a_path"
          @podfile.workspace(path)
          workspace_path = @integrator.send(:workspace_path)
          workspace_path.to_s.should.end_with(path + ".xcworkspace")
          workspace_path.should.be.absolute
          workspace_path.class.should == Pathname
        end

        it "names the workspace after the user project if needed" do
          @integrator.send(:workspace_path).should == temporary_directory + 'SampleProject.xcworkspace'
        end

        it "raises if no workspace could be selected" do
          @integrator.expects(:user_project_paths).returns(%w[ project1 project2 ])
          e = lambda { @integrator.send(:workspace_path) }.should.raise Informative
        end

        it "returns the paths of the user projects" do
          @integrator.send(:user_project_paths).should == [ @sample_project_path ]
        end

        it "skips libraries with empty target definitions" do
          @integrator.targets.map(&:name).should == ["Pods", "Pods-empty"]
          @integrator.send(:targets_to_integrate).map(&:name).should == ['Pods']
        end

      end

      #-----------------------------------------------------------------------#

    end
  end
end
