class InfraCommand

def announce_preflight_info(targets, cfg_synth)

def announce_preflight_info(targets, cfg_synth)
  namespaces    = cfg_synth[:namespace].keys.map(&:to_sym)
  environments  = []
  namespaces.each do |ns_name|
    environments.concat(cfg_synth[:namespace][ns_name].keys.map(&:to_sym))
  end
  preflight_info = []
  preflight_info << %(environments: #{environments})
  preflight_info << %(\n)
  preflight_info << %(namespace: #{targets[0]})
  preflight_info << %(site:      #{targets[1]})
  preflight_info << %(project:   #{targets[2]})
  Say.terminal preflight_info.map(&:strip).join(%(\n))
end

def announce_project(project)

def announce_project(project)
  msg = []
  msg << %(project: #{project[:name]})
  msg << %(src:     #{project[:src]})
  Say.terminal msg.map(&:strip).join(%(\n))
end

def check_run

def check_run
  raise IncorrectSubcommandError unless correct_subcommand?(
    params[:subcommand]
  )
  raise NoInfraTargetError unless params[:target]
end

def check_target(target, config)

${namespace}.${site}.${project}
${namespace}.${site}
${namespace}
targets can be...
def check_target(target, config)
  raise NamespaceNotFoundError if target.nil?
  targets       = target.split('.').map(&:to_sym)
  namespaces    = config[:namespace].keys.map(&:to_sym)
  runtype       = nil
  environments  = []
  namespaces.each do |ns_name|
    environments.concat(config[:namespace][ns_name].keys.map(&:to_sym))
  end
  raise NamespaceNotFoundError unless namespaces.include?(targets[0])
  namespaces.each do |ns_name|
    environments.each do |e_name|
      sites = config[:namespace][ns_name][e_name][:sites] || []
      next if sites.empty?
      site_names = []
      sites.each do |site|
        site_names << site[:name]
      end
      raise SiteNotFoundError unless site_names.include?(targets[1].to_sym)
      projects = config[:namespace][ns_name][e_name][:projects] || []
      next if projects.empty?
      project_names = []
      projects.each do |project|
        project_names << project[:name]
      end
      raise ProjectNotFoundError \
      unless project_names
             .include?(
               targets[2].to_sym
             )
    end
  end
end

def correct_subcommand?(sbcmd)

def correct_subcommand?(sbcmd)
  NAME.to_s.eql?(sbcmd.to_s)
end

def process_target(targets, cfg_synth)

process stage for target
def process_target(targets, cfg_synth)
  namespaces    = cfg_synth[:namespace].keys.map(&:to_sym)
  environments  = []
  namespaces.each do |ns_name|
    environments.concat(cfg_synth[:namespace][ns_name].keys.map(&:to_sym))
  end
  case targets.length.to_i
    # only provided namespace
  when 1
    nil
    # only provided namespace.site
  when 2
    nil
    # only provided namespace.site.project
  when 3
    announce_preflight_info(targets, cfg_synth)
    environments.each do |e_name|
      projects = cfg_synth[:namespace][targets[0]][e_name][:projects]
      projects.each do |project|
        announce_project(project)
        synth = TerraformSynthesizer.new
        case project[:src][:type].to_sym
        when :local
          system %(mkdir -p #{CACHE_DIR}) unless Dir.exist?(CACHE_DIR)
          PROJECT_SRC_DIRS.each do |src_dir|
            next unless File.exist?(File.join(
                                      project[:src][:location].to_s,
                                      %(src),
                                      src_dir.to_s
                                    ))
            synth_files = Dir.glob("#{File.join(
              project[:src][:location].to_s,
              %(src),
              src_dir.to_s
            )}/**/*.rb")
            synth_files.each do |synth_file|
              synth.synthesize(File.read(synth_file))
            end
          end
          Say.terminal JSON.pretty_generate(synth.synthesis)
          project_cache_dir = File.join(CACHE_DIR, project[:name].to_s)
          system %(mkdir -p #{project_cache_dir}) unless Dir.exist?(project_cache_dir)
          File.write(File.join(project_cache_dir, ARTIFACT_FILE), synth.synthesis.to_json)
          system %(cd #{project_cache_dir} && terraform init)
          system %(cd #{project_cache_dir} && terraform plan)
        when :git
          nil
        end
      end
    end
    # fetch project data
    # projet_data = cfg_synth[:namespace][targets[0]]
  end
end

def run(argv)

def run(argv)
  parse(argv)
  # grab a config synth
  cfg_synth = Config.resolve_configurations
  # reject empty configurations
  if cfg_synth.empty?
    Say.terminal %(configuration empty, exiting...)
    exit
  end
  # preflight checks for the command execution
  check_run
  check_target(params[:target], cfg_synth)
  targets = params[:target].split('.').map(&:to_sym)
  process_target(targets, cfg_synth)
  # provide some kind of default exit of the command execution
  exit
end