# rubocop:disable Lint/AssignmentInCondition
# rubocop:disable Style/Next
module Fastlane
  module Actions
    ARGS_MAP = {
      workspace: '-w',
      project: '-p',
      configuration: '-c',
      scheme: '-s',
      clean: '--clean',
      archive: '--archive',
      destination: '-d',
      embed: '-m',
      identity: '-i',
      sdk: '--sdk',
      ipa: '--ipa',
      xcconfig: '--xcconfig',
      xcargs: '--xcargs'
    }

    class IpaAction < Action

      def self.is_supported?(platform)
        platform == :ios
      end

      def self.run(params)
        # The output directory of the IPA and dSYM
        absolute_dest_directory = nil

        # Used to get the final path of the IPA and dSYM
        if dest = params[:destination]
          absolute_dest_directory = File.expand_path(dest)
        end

        # The args we will build with
        # Maps nice developer build parameters to Shenzhen args
        build_args = params_to_build_args(params)

        unless params[:scheme]
          Helper.log.warn "You haven't specified a scheme. This might cause problems. If you can't see any output, please pass a `scheme`"
        end

        # If no dest directory given, default to current directory
        absolute_dest_directory ||= Dir.pwd

        if Helper.test?
          Actions.lane_context[SharedValues::IPA_OUTPUT_PATH] = File.join(absolute_dest_directory, 'test.ipa')
          Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH] = File.join(absolute_dest_directory, 'test.app.dSYM.zip')
          return build_args
        end

        # Joins args into space delimited string
        build_args = build_args.join(' ')

        core_command = "krausefx-ipa build #{build_args} --verbose | xcpretty"
        command = "set -o pipefail && #{core_command}"
        Helper.log.debug command

        begin
          Actions.sh command

          # Finds absolute path of IPA and dSYM
          absolute_ipa_path = find_ipa_file(absolute_dest_directory)
          absolute_dsym_path = find_dsym_file(absolute_dest_directory)

          # Sets shared values to use after this action is performed
          Actions.lane_context[SharedValues::IPA_OUTPUT_PATH] = absolute_ipa_path
          Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH] = absolute_dsym_path
          ENV[SharedValues::IPA_OUTPUT_PATH.to_s] = absolute_ipa_path # for deliver
          ENV[SharedValues::DSYM_OUTPUT_PATH.to_s] = absolute_dsym_path

          Helper.log.info "You are using legacy `shenzhen` to build your app".yellow
          Helper.log.info "It is recommended to upgrade to `gym`".yellow
          Helper.log.info "To do so, just replace `ipa(...)` with `gym(...)` in your Fastfile".yellow
          Helper.log.info "https://github.com/fastlane/gym".yellow
        rescue => ex
          [
            "-------------------------------------------------------",
            "Original Error:",
            " => " + ex.to_s,
            "A build error occured. You are using legacy `shenzhen` for building",
            "it is recommended to upgrade to `gym`: ",
            "https://github.com/fastlane/gym",
            core_command,
            "-------------------------------------------------------"
          ].each do |txt|
            Helper.log.error txt.yellow
          end

          # Raise a custom exception, as the the normal one is useless for the user
          raise "A build error occured, this is usually related to code signing. Take a look at the error above".red
        end
      end

      def self.params_to_build_args(config)
        params = config.values

        params = params.delete_if { |k, v| v.nil? }
        params = fill_in_default_values(params)

        # Maps nice developer param names to Shenzhen's `ipa build` arguments
        params.collect do |k, v|
          v ||= ''
          if ARGS_MAP[k]
            if k == :clean
              v == true ? '--clean' : '--no-clean'
            elsif k == :archive
              v == true ? '--archive' : '--no-archive'
            else
              value = (v.to_s.length > 0 ? "\"#{v}\"" : '')
              "#{ARGS_MAP[k]} #{value}".strip
            end
          end
        end.compact
      end

      def self.fill_in_default_values(params)
        embed = Actions.lane_context[Actions::SharedValues::SIGH_PROFILE_PATH] || ENV["SIGH_PROFILE_PATH"]
        params[:embed] ||= embed if embed
        params
      end

      def self.find_ipa_file(dir)
        # Finds last modified .ipa in the destination directory
        Dir[File.join(dir, '*.ipa')].sort { |a, b| File.mtime(b) <=> File.mtime(a) }.first
      end

      def self.find_dsym_file(dir)
        # Finds last modified .dSYM.zip in the destination directory
        Dir[File.join(dir, '*.dSYM.zip')].sort { |a, b| File.mtime(b) <=> File.mtime(a) }.first
      end

      def self.description
        "Easily build and sign your app using shenzhen"
      end

      def self.details
        [
          "More information on the shenzhen project page: https://github.com/nomad/shenzhen",
          "To make code signing work, it is recommended to set a the provisioning profile in the project settings."
        ].join(' ')
      end

      def self.available_options
        [
          FastlaneCore::ConfigItem.new(key: :workspace,
                                       env_name: "IPA_WORKSPACE",
                                       description: "WORKSPACE Workspace (.xcworkspace) file to use to build app (automatically detected in current directory)",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :project,
                                       env_name: "IPA_PROJECT",
                                       description: "Project (.xcodeproj) file to use to build app (automatically detected in current directory, overridden by --workspace option, if passed)",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :configuration,
                                       env_name: "IPA_CONFIGURATION",
                                       description: "Configuration used to build",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :scheme,
                                       env_name: "IPA_SCHEME",
                                       description: "Scheme used to build app",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :clean,
                                       env_name: "IPA_CLEAN",
                                       description: "Clean project before building",
                                       optional: true,
                                       is_string: false),
          FastlaneCore::ConfigItem.new(key: :archive,
                                       env_name: "IPA_ARCHIVE",
                                       description: "Archive project after building",
                                       optional: true,
                                       is_string: false),
          FastlaneCore::ConfigItem.new(key: :destination,
                                       env_name: "IPA_DESTINATION",
                                       description: "Build destination. Defaults to current directory",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :embed,
                                       env_name: "IPA_EMBED",
                                       description: "Sign .ipa file with .mobileprovision",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :identity,
                                       env_name: "IPA_IDENTITY",
                                       description: "Identity to be used along with --embed",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :sdk,
                                       env_name: "IPA_SDK",
                                       description: "Use SDK as the name or path of the base SDK when building the project",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :ipa,
                                       env_name: "IPA_IPA",
                                       description: "Specify the name of the .ipa file to generate (including file extension)",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :xcconfig,
                                       env_name: "IPA_XCCONFIG",
                                       description: "Use an extra XCCONFIG file to build the app",
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :xcargs,
                                       env_name: "IPA_XCARGS",
                                       description: "Pass additional arguments to xcodebuild when building the app. Be sure to quote multiple args",
                                       optional: true)
        ]
      end

      def self.output
        [
          ['IPA_OUTPUT_PATH', 'The path to the newly generated ipa file'],
          ['DSYM_OUTPUT_PATH', 'The path to the dsym file']
        ]
      end

      def self.author
        "joshdholtz"
      end
    end
  end
end
# rubocop:enable Lint/AssignmentInCondition
# rubocop:enable Style/Next