<commit_before>require 'optparse'
require 'timeout'
require 'yaml'

module DockerRailsProxy
  class Stack < AwsCli
    class Create < self
      YML_EXTENSIONS = %w(.yml .yaml).freeze

      attr_accessor :options, :data, :parameters

      before_initialize do
        'jq is required, `brew install jq`' unless system 'type jq &> /dev/null'
      end

      after_initialize { self.options, self.parameters = {}, {} }
      after_initialize :parse_options!, :set_defaults

      validates { '--profile is required.' if options[:profile].nil? }
      validates { '--ymlfile is required.' if options[:ymlfile].nil? }

      validates do
        unless File.exist? options[:ymlfile]
          "#{options[:ymlfile]} file does not exit"
        end
      end

      validates do
        unless YML_EXTENSIONS.include? File.extname(options[:ymlfile])
          "#{options[:ymlfile]} is not a yml file"
        end
      end

      before_process { self.data = YAML::load_file(options[:ymlfile]) }

      def process
        set_parameters
      end

    private

      def set_parameters
        (data['Parameters'] || {}).each do |key, attrs|
          value = nil

          while parameters[key].to_s.empty? do
            puts '=' * 100
            puts parameters.inspect
            case attrs['Type']
            when 'AWS::EC2::KeyPair::KeyName'
              key_pairs ||= %x(
                aws ec2 describe-key-pairs --profile '#{options[:profile]}' \
                  | jq '.KeyPairs[] | .KeyName' | xargs
              ).strip.split(' ')

              print_options key_pairs, "Choose a key pair number and press [ENTER] (Default: #{value})"
              parameters[key] = get_option(key_pairs, value)
            end
          end
        end
      end

      def print_options(values, message)
        puts message
        values.each_with_index { |v, i| puts "#{i}) #{v}" }
      end

      def get_option(values, default = nil)
        flush_stdin
        print ": "
        option = $stdin.gets.chomp
        option =~ /^\d+$/ ? values[option.to_i] : default
      end

      def flush_stdin
        loop do
          Timeout::timeout(0.1) { $stdin.gets.chomp } rescue break
        end
      end

      def set_defaults
        options[:profile] ||= APP_NAME
      end

      def parse_options!
        opt_parser.parse!(arguments)
      end

      def opt_parser
        @opt_parser ||= OptionParser.new do |opts|
          opts.banner = "Usage: bin/#{APP_NAME} create-stack [options]"

          opts.on(
            '--profile [PROFILE]',<commit_msg>Asks for all parameter values<commit_after>require 'optparse'
require 'timeout'
require 'yaml'

module DockerRailsProxy
  class Stack < AwsCli
    class Create < self
      YML_EXTENSIONS = %w(.yml .yaml).freeze

      attr_accessor :options, :data, :parameters

      before_initialize do
        'jq is required, `brew install jq`' unless system 'type jq &> /dev/null'
      end

      after_initialize { self.options, self.parameters = {}, {} }
      after_initialize :parse_options!, :set_defaults

      validates { '--profile is required.' if options[:profile].nil? }
      validates { '--ymlfile is required.' if options[:ymlfile].nil? }

      validates do
        unless File.exist? options[:ymlfile]
          "#{options[:ymlfile]} file does not exit"
        end
      end

      validates do
        unless YML_EXTENSIONS.include? File.extname(options[:ymlfile])
          "#{options[:ymlfile]} is not a yml file"
        end
      end

      before_process { self.data = YAML::load_file(options[:ymlfile]) }

      def process
        set_parameters
        puts parameters.inspect
      end

    private

      def set_parameters
        (data['Parameters'] || {}).each do |key, attrs|
          value = nil

          while parameters[key].to_s.empty? do
            case attrs['Type']
            when 'AWS::EC2::KeyPair::KeyName'
              key_pairs ||= %x(
                aws ec2 describe-key-pairs --profile '#{options[:profile]}' \
                  | jq '.KeyPairs[] | .KeyName' | xargs
              ).strip.split(' ')

              print_options(key_pairs, "Choose a key pair number and press [ENTER] (Default: #{value})")
              parameters[key] = get_option(key_pairs, value)

            else
              value ||= attrs['Default']

              allowed_values = Array(attrs['AllowedValues'])

              if allowed_values.empty?
                print "Enter #{key} value and press [ENTER] (Default: #{value}): "
                flush_stdin

                parameters[key] = $stdin.gets.chomp || value
                parameters[key] = value if parameters[key].empty?
              else
                print_options(allowed_values, "Choose an option for #{key} and press [ENTER] (Default: #{value})")
                parameters[key] = get_option(allowed_values, value)
              end
            end
          end
        end
      end

      def print_options(values, message)
        puts message
        values.each_with_index { |v, i| puts "#{i}) #{v}" }
      end

      def get_option(values, default = nil)
        flush_stdin
        print ": "
        option = $stdin.gets.chomp

        return default if option.empty?
        option =~ /^\d+$/ ? values[option.to_i] : nil
      end

      def flush_stdin
        loop do
          Timeout::timeout(0.1) { $stdin.gets.chomp } rescue break
        end
      end

      def set_defaults
        options[:profile] ||= APP_NAME
      end

      def parse_options!
        opt_parser.parse!(arguments)
      end

      def opt_parser
        @opt_parser ||= OptionParser.new do |opts|
          opts.banner = "Usage: bin/#{APP_NAME} create-stack [options]"

          opts.on(
            '--profile [PROFILE]',
{'fraction_non_alphanumeric': 0.11249351995852773, 'fraction_numerical': 0.0019008121651978573, 'mean_word_length': 1.9158690176322417, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2227945', 'n_tokens_mistral': 1744, 'n_tokens_neox': 1658, 'n_words': 434}