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}
${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)
  Say.terminal %(planning!)
  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
  Say.terminal JSON.pretty_generate(cfg_synth)
  # 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)
  ###########################################################################
  # modules
  # modules can be fetched from git or local path
  # modules can have a virtual environment to execute in
  ###########################################################################
  namespaces = cfg_synth[:namespace].keys.map(&:to_sym)
  namespaces.each do |namespace_name|
    namespace     = cfg_synth[:namespace][namespace_name]
    context_names = namespace.keys.map(&:to_sym)
    context_names.each do |cn|
      context = namespace[cn]
      modules = context[:modules]
      modules.each do |mod|
        PangeaModule.process(mod)
      end
    end
  end
  ###########################################################################
  # provide some kind of default exit of the command execution
  exit
end