#---
# 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.
#---
require 'model'

# initial builder. Mix of method chaining and parameters.

class RulesBuilder23
  def initialize
    @configuration = Configuration.new
  end

  def item srcSymbol
    @current_item = Item.new srcSymbol
    @configuration.add_item @current_item
    self
  end

  def load aStream
    instance_eval aStream.join("\n")
    @configuration.convert_resources
    return @configuration
  end

  def uses arg
    @current_item.add_usage arg
    self
  end    

  def provides arg
    @current_item.add_provision(arg)
    self
  end

  def depends_on arg
    @current_item.add_dependency(@configuration[arg])
  end


  def resource name, *attributes
    attributes << :name
    new_resource = Struct.new(*attributes)
    @configuration.add_resource_type name, new_resource
  end


  def method_missing sym, *args
    super sym, *args unless @configuration.resource_names.include? sym
    obj = @configuration.resource_type(sym).new
    obj[:name] = sym
    args[0].each_pair do |key, value|
      obj[key] = value
    end
    return obj
  end

    
end

class Configuration
  def add_resource_type name, arg
    @resource_types ||= {}
    @resource_types[name] = arg
  end
  def resource_types
    return @resource_types.values
  end
  def show_resources
    @resource_types.each_value do |r|
      puts r
    end
  end
  def resource_names
    @resource_types.keys
  end
  def resource_type name
    @resource_types[name]
  end
  def convert_resources
    @items.each_value {|i| i.convert_resources}
  end
end

class Item
  def convert_resources
    @provisions = @provisions.map {|r| convert_resource r}
    @uses = @uses.map {|r| convert_resource r}
  end

  def convert_resource arg
    className = arg[:name].to_s
    className[0] = className[0..0].upcase
    klass = Object.const_get className
    p klass
    case arg[:name]
    when :electricity
      return Electricity.new(arg[:power])
    when :acid
      a = Acid.new
      a.grade = arg[:grade]
      a.type = arg[:type]
      return a
    else
      raise "Unknown resoruce class #{arg[:name]}"
    end
  end
end
    

if __FILE__ == $0
  config = RulesBuilder23.new.load(File.readlines('rules23.rb'))
#  config.convert_resources
#  puts config
end

