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

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

module Pod
  describe Installer::Analyzer::SandboxAnalyzer do

    before do
      @spec = fixture_spec('banana-lib/BananaLib.podspec')
      @sandbox = config.sandbox
      lockfile_hash = { 'PODS' => ['BananaLib (1.0)'] }
      @manifest = Pod::Lockfile.new(lockfile_hash)
      @sandbox.stubs(:manifest).returns(@manifest)
      @analyzer = Installer::Analyzer::SandboxAnalyzer.new(@sandbox, [@spec], false)
    end

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

    describe "Analysis" do

      it "returns the sandbox state" do
        @analyzer.stubs(:folder_exist?).returns(true)
        @analyzer.stubs(:folder_empty?).returns(false)
        @analyzer.stubs(:sandbox_checksum).returns(@spec.checksum)
        state = @analyzer.analyze
        state.class.should == Installer::Analyzer::SpecsState
        state.unchanged.should == ["BananaLib"]
      end

      it "marks all the pods as added if no sandbox manifest is available" do
        @sandbox.stubs(:manifest)
        @analyzer.analyze.added.should == ['BananaLib']
      end

    end

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

    describe "Analysis" do

      before do
        @analyzer.stubs(:folder_exist?).returns(true)
        @analyzer.stubs(:folder_empty?).returns(false)
        @analyzer.stubs(:sandbox_checksum).returns(@spec.checksum)
      end

      it "returns whether a Pod is unchanged" do
        @analyzer.send(:pod_state, 'BananaLib').should == :unchanged
      end

      it "considers a Pod as added if it is not recorded in the sandbox manifest" do
        @analyzer.stubs(:sandbox_pods).returns([])
        @analyzer.send(:pod_added?, 'BananaLib').should == true
      end

      it "considers a Pod as added if it folder doesn't exits" do
        @analyzer.stubs(:folder_exist?).returns(false)
        @analyzer.send(:pod_added?, 'BananaLib').should == true
      end

      it "considers deleted a Pod without any resolved specification" do
        @analyzer.stubs(:resolved_pods).returns([])
        @analyzer.send(:pod_deleted?, 'BananaLib').should == true
      end

      it "considers changed a Pod whose versions do not match" do
        @analyzer.stubs(:sandbox_version).returns(Version.new(999))
        @analyzer.send(:pod_changed?, 'BananaLib').should == true
      end

      it "considers changed a Pod whose checksums do not match" do
        @analyzer.stubs(:sandbox_checksum).returns('SHA')
        @analyzer.send(:pod_changed?, 'BananaLib').should == true
      end

      it "considers changed a Pod whose activated specifications do not match" do
        @analyzer.stubs(:sandbox_spec_names).returns(['BananaLib', 'BananaLib/Subspec'])
        @analyzer.send(:pod_changed?, 'BananaLib').should == true
      end

      it "considers changed a Pod whose folder is empty" do
        @analyzer.stubs(:folder_empty?).returns(true)
        @analyzer.send(:pod_changed?, 'BananaLib').should == true
      end

      it "considers changed a Pod which has been pre-downloaded" do
        @sandbox.stubs(:predownloaded?).returns(true)
        @analyzer.send(:pod_changed?, 'BananaLib').should == true
      end

      it "considers changed a Pod whose head state doesn't match" do
        @sandbox.stubs(:head_pod?).returns(true)
        @analyzer.send(:pod_changed?, 'BananaLib').should == true
      end

      it "considers changed a Pod whose specification is in head mode if in update mode" do
        @sandbox.stubs(:head_pod?).returns(true)
        @analyzer.stubs(:update_mode).returns(true)
        @analyzer.send(:pod_changed?, 'BananaLib').should == true
      end

      it "doesn't consider changed a Pod whose specification is in head mode if not in update mode" do
        @sandbox.stubs(:head_pod?).returns(true)
        @analyzer.stubs(:sandbox_head_version?).returns(true)
        @analyzer.stubs(:update_mode).returns(false)
        @analyzer.send(:pod_changed?, 'BananaLib').should == false
      end

    end

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

    describe "Private helpers" do

      it "returns the sandbox manifest" do
        @analyzer.send(:sandbox_manifest).should == @manifest
      end

      it "returns the lockfile as the sandbox if one is not available" do
        lockfile = Lockfile.new({})
        @sandbox.stubs(:manifest)
        @analyzer.stubs(:lockfile).returns(lockfile)
        @analyzer.send(:sandbox_manifest).should == lockfile
      end

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

      it "returns the root name of the resolved Pods" do
        subspec = Spec.new(@spec, 'Subspec')
        @analyzer.stubs(:specs).returns([@spec, subspec])
        @analyzer.send(:resolved_pods).should == ['BananaLib']
      end

      it "returns the root name of pods stored in the sandbox manifest" do
        @manifest.stubs(:pod_names).returns(['BananaLib', 'BananaLib/Subspec'])
        @analyzer.send(:sandbox_pods).should == ['BananaLib']
      end

      it "returns the name of the resolved specifications sorted by name" do
        subspec = Spec.new(@spec, 'Subspec')
        @analyzer.stubs(:specs).returns([subspec, @spec])
        @analyzer.send(:resolved_spec_names, 'BananaLib').should == ['BananaLib', 'BananaLib/Subspec']
      end

      it "returns the name of the specifications stored in the sandbox manifest" do
        @manifest.stubs(:pod_names).returns(['BananaLib', 'BananaLib/Subspec'])
        @analyzer.send(:sandbox_spec_names, 'BananaLib').should == ['BananaLib', 'BananaLib/Subspec']
      end

      it "returns the root specification for the Pod with the given name" do
        subspec = Spec.new(@spec, 'Subspec')
        @analyzer.stubs(:specs).returns([@spec, subspec])
        @analyzer.send(:root_spec, 'BananaLib').should == @spec
      end

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

      it "returns the version for the Pod with the given name stored in the manifest" do
        @analyzer.send(:sandbox_version, 'BananaLib').should == Version.new('1.0')
      end

      it "returns the checksum for the spec of the Pods with the given name stored in the manifest" do
        @manifest.stubs(:checksum).returns(@spec.checksum)
        @analyzer.send(:sandbox_checksum, 'BananaLib').should == @spec.checksum
      end

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

      it "returns whether the folder containing the Pod with the given name is empty" do
        @analyzer.send(:folder_exist?, 'BananaLib').should.be.false
        path = temporary_directory + 'Pods/BananaLib'
        path.mkpath
        @analyzer.send(:folder_exist?, 'BananaLib').should.be.true

      end

      it "returns whether the folder containing the Pod with the given name is empty" do
        @analyzer.send(:folder_empty?, 'BananaLib').should.be.true
        path = temporary_directory + 'Pods/BananaLib'
        path.mkpath
        File.open(path + "file", "w") {}
        @analyzer.send(:folder_empty?, 'BananaLib').should.be.false
      end

    end

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

  end
end
