module Kz
  module SidebarFactory
    @@entries = nil

    module_function
    def entries
      Kz.barrier([]) do
        if @@entries.nil?
          load_sidebars
          @@entries = {}
          ObjectSpace.each_object(Class) do |klass|
            if klass.respond_to?(:sidebar_entry?) and klass.sidebar_entry? and
                klass.respond_to?(:priority_hint) and
                klass.respond_to?(:label) and
                klass.respond_to?(:icon) and
                klass.respond_to?(:create)
              @@entries[klass.label] = klass
            end
          end
        end
        @@entries.collect do |key, entry|
          [entry.priority_hint, entry.label, entry.icon]
        end
      end
    end

    def create(label, sidebar)
      Kz.barrier do
        return nil unless @@entries.has_key?(label)
        entry = @@entries[label]
        entry.create(sidebar)
      end
    end

    def load_sidebars
      search_dirs.each do |dir|
        next unless File.exist?(dir)
        Dir[File.join(dir, "*.rb")].each do |sidebar|
          Kz.barrier do
            require sidebar.sub(/\.rb/, '')
          end
        end
      end
    end

    def search_dirs
      dirs = $LOAD_PATH.collect do |path|
        File.join(File.expand_path(path), "kz", "sidebars")
      end
      dirs.unshift(Kz::SIDEBARS_DIR)
      dirs
    end
  end
end
