require 'Borges'

module ObjectSpaceBrowser

  class Klasses < Borges::Component

    ##
    # Fetches all the Classes defined sorted by name

    def klasses
      klasses = []

      ObjectSpace.each_object(Class) do |klass| klasses << klass end

      return klasses.sort_by do |k| k.name end
    end

    def choose(klass)
      call(Klass.new(klass))
    end

    def render_content_on(r)
      r.heading "Classes"

      r.list_do(klasses) do |klass|
        r.anchor(klass.name) do choose klass end
      end
    end

    def will_answer?
      return false
    end

    register_application('object_browser')

  end

  class Klass < Borges::Component

    def initialize(klass)
      @klass = klass
      set_instances
    end

    def choose(instance)
      call Instance.new(instance)
    end

    ##
    # Fetches all instances of the klass sorted by object_id

    def set_instances
      instances = []

      if @klass == Symbol then
        @instances = Symbol.all_symbols.sort_by do |s| s.to_s end
      else
        ObjectSpace.each_object(@klass) do |obj| instances << obj end
        @instances = instances.sort_by do |i| i.object_id end
      end
    end

    def render_content_on(r)
      instances = @instances
      r.heading "Class #{@klass.name}"

      r.heading_level "#{instances.length} Instances", 2

      return if instances.length.zero?

      #if @klass == Symbol then
      #  r.list_do(instances) do |instance|
      #    r.anchor(instance) do choose(instance) end
      #  end
      #else
        r.list_do(instances) do |instance|
          r.anchor("0x%x" % instance.object_id) do choose(instance) end
        end
      #end
    end

    def will_answer?
      return false
    end

  end

  class Instance < Borges::Component

    def initialize(instance)
      @instance = instance
    end

    def render_content_on(r)
      r.heading "Instance 0x%x of #{@instance.class.name}" % @instance.object_id

      r.table do
        r.table_headings "Instance Variable", "Object"
        @instance.instance_variables.each do |var|
          render_ivar_row(var, r)
        end
      end
    end

    def render_ivar_row(var, r)
      r.table_row do
        r.table_data var
        r.table_data do
          r.encode_text @instance.instance_variable_get(var).inspect
        end
      end
    end

    def will_answer?
      return false
    end

  end

end # module ObjectSpaceBrowser

if $0 == __FILE__ then
  require 'Borges/WEBrick'
  Borges::WEBrickServlet.start
end

