class Concourse

def self.default_execute_args task

def self.default_execute_args task
  args = []
  task["config"]["inputs"].each do |input|
    args << "--input=#{input["name"]}=."
  end
  args.join(" ")
end

def self.production_rubies

def self.production_rubies
  RUBIES[:mri].reject { |r| r =~ /rc/ }
end

def self.rc_rubies

def self.rc_rubies
  RUBIES[:mri].select { |r| r =~ /rc/ }
end

def self.url_for fly_target

def self.url_for fly_target
  matching_line = `fly targets`.split("\n").grep(/^#{fly_target}/).first
  raise "invalid fly target #{fly_target}" unless matching_line
  matching_line.split(/ +/)[1]
end

def self.validate_fly_target task, task_args

def self.validate_fly_target task, task_args
  unless task_args[:fly_target]
    raise "ERROR: must specify a fly target, like `rake #{task.name}[targetname]`"
  end
  return task_args[:fly_target]
end

def create_tasks!

def create_tasks!
  unless Dir.exist? directory
    mkdir_p directory
  end
  unless File.exist? pipeline_erb_filename
    warn "WARNING: concourse template #{pipeline_erb_filename.inspect} does not exist, run `rake concourse:init`"
  end
  CLOBBER.include pipeline_filename if defined?(CLOBBER)
  namespace :concourse do
    #
    #  project commands
    #
    desc "bootstrap a concourse config"
    task :init do
      rake_init
    end
    #
    #  pipeline commands
    #
    desc "generate and validate the pipeline file for #{project_name}"
    task "generate" do |t|
      File.open pipeline_filename, "w" do |f|
        f.write erbify(File.read(pipeline_erb_filename))
      end
      sh "fly validate-pipeline -c #{pipeline_filename}"
    end
    desc "upload the pipeline file for #{project_name}"
    task "set", [:fly_target] => ["generate"] do |t, args|
      fly_target = Concourse.validate_fly_target t, args
      options = [
        "-p '#{project_name}'",
        "-c '#{pipeline_filename}'",
      ]
      if File.exist? private_var_file
        puts "using #{private_var_file} to resolve template vars"
        options << "-l '#{private_var_file}'"
      end
      sh "fly -t #{fly_target} set-pipeline #{options.join(" ")}"
    end
    %w[expose hide pause unpause destroy].each do |command|
      desc "#{command} the #{project_name} pipeline"
      task "#{command}", [:fly_target] do |t, args|
        fly_target = Concourse.validate_fly_target t, args
        sh "fly -t #{fly_target} #{command}-pipeline -p #{project_name}"
      end
    end
    desc "remove generate pipeline file"
    task "clean" do |t|
      rm_f pipeline_filename
    end
    #
    #  task commands
    #
    desc "list all the available tasks from the #{project_name} pipeline"
    task "tasks" => "generate" do
      tasks = []
      each_task do |job, task|
        tasks << "#{job["name"]}/#{task["task"]}"
      end
      puts "Available Concourse tasks for #{project_name} are:"
      tasks.sort.each { |task| puts " * #{task}" }
    end
    desc "fly execute the specified task"
    task "task", [:fly_target, :job_task, :fly_execute_args] => "generate" do |t, args|
      fly_target = Concourse.validate_fly_target t, args
      job_task = args[:job_task]
      unless job_task
        raise "ERROR: must specify a task name, like `rake #{t.name}[target,taskname]`"
      end
      concourse_task = find_task job_task
      raise "ERROR: could not find task `#{job_task}`" unless concourse_task
      fly_execute_args = args[:fly_execute_args] || Concourse.default_execute_args(concourse_task)
      puts concourse_task.to_yaml
      Tempfile.create("concourse-task") do |f|
        f.write concourse_task["config"].to_yaml
        f.close
        Bundler.with_clean_env do
          sh "fly -t #{fly_target} execute #{fly_execute_args} -c #{f.path}"
        end
      end
    end
    #
    #  builds commands
    #
    desc "abort all running builds for this pipeline"
    task "abort-builds", [:fly_target] do |t, args|
      fly_target = Concourse.validate_fly_target t, args
      `fly -t #{fly_target} builds`.split("\n").each do |line|
        pipeline_job, build_id, status = *line.split(/\s+/)[1,3]
        next unless status == "started"
        sh "fly -t #{fly_target} abort-build -j #{pipeline_job} -b #{build_id}"
      end
    end
  end
end

def each_job

def each_job
  pipeline = YAML.load_file(pipeline_filename)
  pipeline["jobs"].each do |job|
    yield job
  end
end

def each_task

def each_task
  each_job do |job|
    job["plan"].each do |task|
      yield job, task if task["task"]
    end
  end
end

def erbify document_string, *args

def erbify document_string, *args
  ERB.new(document_string, nil, "%-").result(binding)
end

def find_task job_task

def find_task job_task
  job_name, task_name = *job_task.split("/")
  each_task do |job, task|
    return task if task["task"] == task_name && job["name"] == job_name
  end
  nil
end

def initialize project_name, args={}

def initialize project_name, args={}
  @project_name = project_name
  @directory = args[:directory] || DEFAULT_DIRECTORY
  @pipeline_filename = File.join(@directory, "#{project_name}.final.yml")
  @pipeline_erb_filename = File.join(@directory, "#{project_name}.yml")
  @private_var_file = File.join(@directory, "private.yml")
end

def rake_init

def rake_init
  FileUtils.mkdir_p File.join(directory, "tasks")
  FileUtils.touch pipeline_erb_filename
  File.open ".gitignore", "a" do |f|
    f.puts private_var_file
    f.puts pipeline_filename
  end
end