class ApplicationHelper::Toolbar::Basic < ApplicationHelper::Toolbar::Base
  def definition(record = nil)
    extension_classes_filtered(record).reduce(@definition) do |acc, ext|
      acc.merge(ext.definition)
    end
  end

  private

  def extension_classes
    @extension_classes ||= load_extension_classes
  end

  def extension_classes_filtered(record)
    return extension_classes if record.nil?

    # Example:
    # "ManageIQ::Providers::Amazon::ToolbarOverrides::EmsCloudCenter" is a match for
    #   "ManageIQ::Providers::Amazon::CloudManager
    extension_classes.find_all do |ext|
      ext.name.split('::')[0..2] == record.class.name.split('::')[0..2]
    end
  end

  def load_extension_classes
    return [] if self.class.name.nil?

    toolbar_base_name = self.class.name.to_s.split('::').last
    Vmdb::Plugins.collect do |plugin|
      instance = [plugin.name.chomp('::Engine'), 'ToolbarOverrides', toolbar_base_name].join('::')
      instance.safe_constantize
    end.compact
  end
end

class ApplicationHelper::Toolbar::Basic < ApplicationHelper::Toolbar::Base
  def definition(record = nil)
    extension_classes_filtered(record).reduce(@definition) do |acc, ext|
      acc.merge(ext.definition)
    end
  end

  private

  def extension_classes
    @extension_classes ||= load_extension_classes
  end

  def extension_classes_filtered(record)
    # If the toolbar class reponds to `record_valid?`, we call it. Even for null record.
    #
    # Else we use a mechanism that matches records with provider names.
    # In this case null record means "match".
    #
    # Example for matching:
    #
    # "ManageIQ::Providers::Amazon::ToolbarOverrides::EmsCloudCenter" is a match for
    #   "ManageIQ::Providers::Amazon::CloudManager
    extension_classes.find_all do |ext|
      ext.respond_to?(:record_valid?) ?
        ext.record_valid?(record) :
        (record.nil? || ext.name.split('::')[0..2] == record.class.name.split('::')[0..2])
    end
  end

  def load_extension_classes
    return [] if self.class.name.nil?

    toolbar_base_name = self.class.name.to_s.split('::').last
    Vmdb::Plugins.collect do |plugin|
      instance = [plugin.name.chomp('::Engine'), 'ToolbarOverrides', toolbar_base_name].join('::')
      instance.safe_constantize
    end.compact
  end
end

Extend toolbar pluggability to all plugins.
Extend toolbar pluggability to all plugins.

Newly any plugin can add content to to toolbars. Not only providers.

Plugged-in toolbars should implement class method:

def self.record_valid?(record)
    ...
end

that decides if the toolbar is to be displayed for a particular record.

Example display only for RHEV VMs:

def self.record_valid?(record)
  record.kind_of?(ManageIQ::Providers::Vmware::InfraManager::Vm)
end

Please note that such level of control is only available for the
toolbars on the detail pages. Not for the toolbars on the listing pages.
