['lib', File.join('..','lib'), '.', '..'].each do |path|
  $:.unshift path
end
require 'flow'


class AbstractJob
  attr :name
  def initialize args
    @name = args[:name] 
  end
end

# the most basic requirement is to have a class with a 'run' method and a name
class JobWithSimpleRun < AbstractJob
  def initialize args 
    super
    @result = args[:result]
  end
  def run
    return @result
  end
end

# optionally, the run method can take arguments, in which case a hash will be
# passed to the job with keys :flow, :config, :flowargs, and :results,
# :results itself is a hash with an entry for each dependent job, :flowargs
# consists of an Array of any args passed to the run method of the flow itself
class JobWithArityRun < AbstractJob
  def run(results)
    return((results[:a] << 1) + (results[:b] << 2))
  end
end

# jobs with a configure method will be configured via the flow's config
# _before_ running
class JobWithArityRunAndConfigure < AbstractJob
  def run(results)
    return(results[:c] + @result)
  end
  def configure(config)
    @result = config[:result]
  end
end


# flows are constructed out of a dag of jobs - a hash representing a dependacy
# graph

# create all the jobs
a = JobWithSimpleRun.new :name => :a, :result => 10
b = JobWithSimpleRun.new :name => :b, :result => 5 
c = JobWithArityRun.new :name => :c
d = JobWithArityRunAndConfigure.new :name => :d


# a and b depend on nothing, c depends on a and b, d depends on c
dag = {
  a => nil, b => nil, c => [a, b], d => [c]
}

flow = Flow.new dag

# each job may have a config, here only :d does
config = {
  :d => { :result => 2 }
}

flow.configure config

# finally, we run the flow
results = flow.run

# the result of each job is hashed on name 
p results
