module Fastlane
  module Actions
    module SharedValues
      VERSION_CODE = :VERSION_CODE
    end

    class IncrementVersionCodeAction < Action
      require 'shellwords'

      def self.run(params)
        # Fastlane takes care of reading in the parameter and fetching the environment variable:
        UI.message "Using file #{params[:file]} to increment the value of variable named \"#{params[:var_name]}\""
        UI.message "Use specific version code: #{params[:code_num].to_s}" unless !params[:code_num]
	
	# Define the regular expression to extract and replace the version code variable
        re = "^(\\s*(#{params[:var_name]})([^:]*:?\\s+|\\s*=\\s*))([0-9]+)(\\s*((\\/\\/|#).*)?)$"
        # Construct the sed command to extract the version code from the targeted file
        sed_cmd_print = "#{params[:sed_cmd]} -n -e 's/#{re}/\\4/ p' #{params[:file]}"

        # Extract current version code
        code_current = sh(sed_cmd_print, print_command: params[:verbose], print_command_output: params[:verbose]).split("\n").first.strip.to_i
        UI.message "Current version code: #{code_current.to_s}"
        # Determine the next version code from parameter or by incrementing the current one
        code_next = (params[:code_num] ? params[:code_num].to_i : code_current + 1)
        # Store the new version code in the targeted file
        if Helper.test?
          Actions.lane_context[SharedValues::BUILD_NUMBER] = sed_cmd_print
          code_new = code_next
        else
          sed_cmd_replace = "#{params[:sed_cmd]} -i -e 's/#{re}/\\1#{code_next}\\5/' #{params[:file]}"
          sh(sed_cmd_replace, print_command: params[:verbose], print_command_output: params[:verbose])
          # Extract the new version code
          code_new = sh(sed_cmd_print, print_command: params[:verbose], print_command_output: params[:verbose]).split("\n").first.strip.to_i
        end
        UI.message "New version code: #{code_new.to_s}"

        Actions.lane_context[SharedValues::VERSION_CODE] = code_new
        return code_new
      end

      #####################################################
      # @!group Documentation
      #####################################################

      def self.description
        "Increment the version code of your Android project"
      end

      def self.details
        "This action offers for (recent/Gradle) Android projects similar features as increment_build_number does for XCode projects"
      end

      def self.available_options
        # Define all options this action supports. 
        [
          FastlaneCore::ConfigItem.new(key: :verbose,
                                       env_name: "FL_INCREMENT_VERSION_CODE_VERBOSE",
                                       description: "optional, set to true to be more verbose",
                                       optional: true,
                                       is_string: false,
                                       default_value: false),
          FastlaneCore::ConfigItem.new(key: :sed_cmd,
                                       env_name: "FL_INCREMENT_VERSION_CODE_SED_CMD",
                                       description: "optional, you must specify the sed command with correct switche for extended regexp support",
                                       optional: true,
                                       default_value: "sed -r"), # TODO: adapt for non-GNU version of sed (e.g.: "sed -E" for MacOS)
          FastlaneCore::ConfigItem.new(key: :var_name,
                                       env_name: "FL_INCREMENT_VERSION_CODE_VAR_NAME",
                                       description: "optional, you must specify the name of the variable that holds the value to be changed",
                                       optional: true,
                                       default_value: "versionCode"),
          FastlaneCore::ConfigItem.new(key: :file,
                                       env_name: "FL_INCREMENT_VERSION_CODE_FILE",
                                       description: "optional, you must specify the path to the config file that holds the value to be changed",
                                       optional: true,
                                       verify_block: proc do |value|
                                         UI.user_error!("Could not find config file") if !File.exist?(value) and !Helper.is_test?
                                       end,
                                       default_value: "app/build.gradle"),
          FastlaneCore::ConfigItem.new(key: :code_num,
                                       env_name: "FL_INCREMENT_VERSION_CODE_NUM",
                                       description: "Change to a specific version code number",
                                       optional: true,
                                       is_string: false)
        ]
      end

      def self.output
        # Define the shared values this action provides
        [
          ['VERSION_CODE', 'The new version code']
        ]
      end

      def self.return_value
        "Returns the new version code value"
      end

      def self.authors
        ["btlogy"]
      end

      def self.is_supported?(platform)
        [:android].include?(platform)
      end
    end
  end
end
