# frozen_string_literal: true

require 'rexml/document'
require 'rss'

class FeedElementInstaller
  private_class_method :new

  def self.install(element_name, feed)
    # RSS Specification at http://cyber.harvard.edu/rss/rss.html#extendingRss
    # > A RSS feed may contain [non-standard elements], only if those elements are *defined in a namespace*

    new(element_name, feed).install if element_name.include?(':')
  end

  attr_reader :feed, :original_name, :element_namespace, :element_name, :element_accessor

  def initialize(element_name, feed)
    @feed = feed
    @original_name = element_name
    @element_namespace, @element_name = *element_name.split(':')
    @element_accessor = "#{@element_namespace}_#{@element_name}"
  end

  def element_uri
    @element_uri ||= REXML::Document.new(feed).root&.attributes&.namespaces&.fetch(@element_namespace, '') || ''
  end

  def install
    install_in_rss unless installed_in_rss?
    install_in_atom unless installed_in_atom?
  end

  private

  def install_in_rss
    RSS::Rss::Channel::Item.install_text_element(element_name, element_uri, '?', element_accessor, nil, original_name)
    RSS::BaseListener.install_get_text_element(element_uri, element_name, element_accessor)
  end

  def install_in_atom
    RSS::Atom::Entry.install_text_element(element_name, element_uri, '?', element_accessor, nil, original_name)
    RSS::Atom::Feed::Entry.install_text_element(element_name, element_uri, '?', element_accessor, nil, original_name)
    RSS::BaseListener.install_get_text_element(element_uri, element_name, element_accessor)
  end

  def installed_in_rss?
    RSS::Rss::Channel::Item.method_defined?(element_accessor)
  end

  def installed_in_atom?
    RSS::Atom::Entry.method_defined?(element_accessor) || RSS::Atom::Feed::Entry.method_defined?(element_accessor)
  end
end
