class ReportTemplateManager

  def initialize
    @names = {}
  end

  def plugins
    # This substraction is a bit inelegant...
    # UPGRADE: remove Plugins::Export
    # @vendorized_plugins ||= (Plugins::Export.included_modules - [ProjectExport])
    @vendorized_plugins ||= []
    @gemified_plugins   ||= Dradis::Plugins.with_feature(:export)
    @plugins            ||= @vendorized_plugins.concat(@gemified_plugins).sort{ |a,b| a.name <=> b.name }
    @plugins ||= Dradis::Plugins.with_feature(:export).sort{ |a,b| a.name <=> b.name }
  end

  def each_plugin
    plugins.each do |plugin|
      yield plugin, name_for_plugin(plugin), templates_for_plugin(plugin)
    end
  end

  # The human name of a plugin doesn't change with time, thus it makes sense to
  # memoize it.
  def name_for_plugin(plugin)
    @names[plugin] ||= underscored_name_for_plugin(plugin).humanize.gsub(/\//,' - ')
  end

  # Returns an array holding every template in the system, disregarding the plugin
  #
  # TODO
  #
  # We need to add a #plugin field so we can keep track of templates with the
  # same name for different plugins
  #
  def templates
    plugins.map{ |p| templates_for_plugin(p) }.flatten.uniq
  end

  # Returns an array of ReportTemplateProperties objects, one for each template
  # in the system. Only retrieves templates if they have a ReportTemplateProperties
  # instance associated to it.
  #
  # TODO
  #
  # We need to add a #plugin field so we can keep track of templates with the
  # same name for different plugins
  #
  def template_properties
    templates.map do |t|
      ReportTemplateProperties.find_by_template_file(t)
    end.compact
  end

  # This method looks for available templates inside the location given by the
  # admin:paths:templates:reports setting.
  #
  # Since the list of templates may change over a given session, we don't cache
  # the list.
  def templates_for_plugin(plugin)
    template_folder = templates_folder_for_plugin(plugin)
    return [] unless File.exists?(template_folder)

    Dir.entries(template_folder).sort.select{|file| File.file?(template_folder.join(file)) }
  end

  # This method returns the folder corresponding to the paths:templates:reports
  # setting and the plugin name's subfolder.
  #
  # Eventually this should be the only point in the application where that
  # setting is ever used.
  def templates_folder_for_plugin(plugin)
    Pathname.new(File.join(::Configuration.paths_templates_reports, underscored_name_for_plugin(plugin)))
  end

  # Supports both gemified ("Dradis::Plugins::PluginName::Engine")
  # and vendorized ("PluginName") plugin names
  def underscored_name_for_plugin(plugin)
    name = plugin.name.split("::")[2] || plugin.name
    name.underscore
  end
end
