module Pod
  class Installer
    class UserProjectIntegrator
      class TargetIntegrator
        # Configures an user target to use the CocoaPods xcconfigs which allow
        # lo link against the Pods.
        #
        class XCConfigIntegrator
          # Integrates the user target.
          #
          # @param  [Target::AggregateTarget] pod_bundle
          #         The Pods bundle.
          #
          # @param  [Array<PBXNativeTarget>] targets
          #         The native targets associated which should be integrated
          #         with the Pod bundle.
          #
          def self.integrate(pod_bundle, targets)
            targets.each do |target|
              target.build_configurations.each do |config|
                update_from_cocoapods_0_33_1(pod_bundle, targets)
                set_target_xcconfig(pod_bundle, config)
                check_overrides(pod_bundle, target, config)
              end
            end
          end

          private

          # @!group Integration steps
          #-------------------------------------------------------------------#

          # Removes the xcconfig used up to CocoaPods 0.33 from the project and
          # deletes the file it if exists.
          #
          # @param  [Target::AggregateTarget] pod_bundle
          #         The Pods bundle.
          #
          # @param  [XcodeProj::PBXNativeTarget] target
          #         The native targets.
          #
          # @todo   This can be removed for CocoaPods 1.0
          #
          def self.update_from_cocoapods_0_33_1(pod_bundle, targets)
            targets.map(&:project).uniq.each do |project|
              path = pod_bundle.xcconfig_relative_path(nil)
              file_ref = project.files.find { |f| f.path == path }
              if file_ref
                UI.message "- Removing (#{path})" do
                  file_ref.remove_from_project
                  absolute_path = pod_bundle.xcconfig_path
                  File.delete(absolute_path) if File.exist?(absolute_path)
                end
              end
            end
          end

          # Creates a file reference to the xcconfig generated by
          # CocoaPods (if needed) and sets it as the base configuration of
          # build configuration of the user target.
          #
          # @param  [Target::AggregateTarget] pod_bundle
          #         The Pods bundle.
          #
          # @param  [[Xcodeproj::XCBuildConfiguration] config
          #         The build configuration.
          #
          def self.set_target_xcconfig(pod_bundle, config)
            path = pod_bundle.xcconfig_relative_path(config.name)
            file_ref = config.project.files.find { |f| f.path == path }
            file_ref ||= config.project.new_file(path)
            config.base_configuration_reference = file_ref
          end

          # Checks whether the settings of the CocoaPods generated xcconfig are
          # overridden by the build configuration of a target and prints a
          # warning to inform the user if needed.
          #
          # @param  [Target::AggregateTarget] pod_bundle
          #         The Pods bundle.
          #
          # @param  [XcodeProj::PBXNativeTarget] target
          #         The native target.
          #
          # @param  [Xcodeproj::XCBuildConfiguration] config
          #         The build configuration.
          #
          def self.check_overrides(pod_bundle, target, config)
            xcconfig = pod_bundle.xcconfigs[config.name]
            xcconfig.attributes.keys.each do |key|
              target_value = config.build_settings[key]
              if target_value && !target_value.include?('$(inherited)')
                print_override_warning(pod_bundle, target, config, key)
              end
            end
          end

          private

          # @!group Private helpers
          #-------------------------------------------------------------------#

          # Prints a warning informing the user that a build configuration of
          # the integrated target is overriding the CocoaPods build settings.
          #
          # @param  [Target::AggregateTarget] pod_bundle
          #         The Pods bundle.
          #
          # @param  [XcodeProj::PBXNativeTarget] target
          #         The native target.
          #
          # @param  [Xcodeproj::XCBuildConfiguration] config
          #         The build configuration.
          #
          # @param  [String] key
          #         The key of the overridden build setting.
          #
          def self.print_override_warning(pod_bundle, target, config, key)
            actions = [
              "Use the `$(inherited)` flag, or",
              "Remove the build settings from the target."
            ]
            message = "The `#{target.name} [#{config.name}]` " \
              "target overrides the `#{key}` build setting defined in " \
              "`#{pod_bundle.xcconfig_relative_path(config.name)}'." \
              "This can lead to problems with the CocoaPods installation"
            UI.warn(message, actions)
          end
        end
      end
    end
  end
end
