#---
# 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.
#---

class Configuration
  def initialize
    @items = {}
  end
  def add_item arg
    @items[arg.id] = arg
  end
  def [] arg
    return @items[arg]
  end
  def items
    @items.values
  end
end



class Item 
  attr_reader :id, :uses, :provisions, :dependencies
  def initialize id
    @id = id
    @uses = []
    @provisions = []
    @dependencies = []
  end
  def add_usage anItem
    @uses << anItem
  end
  def add_provision anItem
    @provisions << anItem
  end
  def add_dependency anItem
    @dependencies << anItem
  end
end

class Acid
  attr_accessor :type, :grade
end

class Electricity 
  def initialize power
    @power = power
  end
  attr_reader :power
end


class Notification
  def initialize
    @messages = []
  end
  def fail message = "uncommunicative failure"
    @messages << message
  end
  def ok?
    return @messages.empty?
  end
  def error message
    @messages << message
  end
  def to_s
    return 'OK' if ok?
    result = ['Failed']
    @messages.each {|m| result << m.to_s }
    return result.join("\n")
  end
end


class Item 
  def to_s
    "%s\n  uses: {%s}\n  provides{%s}\n  =>{%s}" % 
      [@id, @uses.join(", "), @provisions.join(", "), 
      @dependencies.collect{|d| d.id}.join(", ")]
  end
  def check
    raise "Item invalid" unless validate.ok?
  end
  def validate
    result = Notification.new
    result.error "bad resource in uses" unless 
      @uses.all?{|r| resource? r}
    result.error "bad resource in provision" unless 
      @provisions.all?{|r| resource? r}
    return result
  end
  def resource? anObject
    return [Electricity, Acid].include?(anObject.class)
  end
end

class Acid
  def to_s
    "Acid[%s,%d]" % [@type, @grade]
  end
end

class Electricity
  def to_s
    "Elec[%d]" % @power
  end
end

class Configuration
  def to_s
    "Config\n" + items.join("\n")
  end
end

