#---
# Excerpted from "The ThoughtWorks Anthology",
# published by The Pragmatic Bookshelf.
# Copyrights apply to this code. It may not be used to create training material, 
# courses, books, articles, and the like. Contact us if you are in doubt.
# We make no guarantees that this code is fit for any purpose. 
# Visit http://www.pragmaticprogrammer.com/titles/twa for more book information.
#---
# I've left acid and item using explicit parent calls and electricity
# builder using method missing at the moment to see how I want to talk
# about them


require 'model'
require 'pp'
class RulesBuilder15
  def load aStream
    result = eval(aStream.join("\n"))
    return result.configuration
  end
end


class ConfigurationBuilder
  attr_reader :subject
  def self.item arg
    builder = ConfigurationBuilder.new
    builder.item arg
  end
  def initialize
    @subject = Configuration.new
  end
  def item arg
    result = ItemBuilder.new(self, arg)
    @subject.add_item result.subject
    return result
  end
end

class ItemBuilder
  attr_reader :subject, :parent
  def initialize parent, name
    @parent = parent
    @subject = Item.new name
  end
  def item arg
    @parent.item arg
  end
  def provides 
    @capturing = :provisions
    self
  end
  def uses
    @capturing = :uses
    return self
  end    
  def capture arg
    case @capturing
    when :uses
      @subject.add_usage arg.subject
    when :provisions
      @subject.add_provision arg.subject
    else
      raise "Bad capture state"
    end
  end    

  def depends_on arg
    subject.add_dependency(configuration[arg])
    return self
  end
  def configuration
    return @parent.subject
  end
  def acid 
    resource = AcidBuilder.new(self)
    capture resource
    return resource
  end
  def electricity power 
    resource = ElectricityBuilder.new(self, power)
    capture resource
    return resource
  end
    
end


class AcidBuilder
  attr_reader :subject, :parent
  def initialize parent
    @parent = parent
    @subject = Acid.new
  end
  def type arg
    subject.type = arg
    self
  end
  def grade arg
    subject.grade = arg
    self
  end

#----- use missing
  def uses
    @parent.uses
  end
  def item arg
    @parent.item arg
  end
  def depends_on arg
    @parent.depends_on arg
  end
end

class ElectricityBuilder
  attr_reader :subject, :parent
  def initialize parent, power
    @parent = parent
    @subject = Electricity.new power
  end
  def method_missing name, *args
    @parent.send(name, *args)
  end
end

if __FILE__ == $0
  c = RulesBuilder15.new.load(File.readlines('rules15.rb'))

end


    
