# frozen_string_literal: true

module Junoser
  module Xsd
    module Base
      attr_reader :xml, :parent

      OFFSET = '  '

      def initialize(xml, options = {})
        @xml = xml
        @depth = options[:depth] || 0
        @parent = options[:parent]
      end

      def config
        raise 'ERROR: no implementation'
      end

      def children
        @children ||= xml.xpath('./*[not(self::xsd:annotation)]')
      end

      def root?
        @depth == 1
      end

      def inspect
        ["#<#{self.class}:0x#{object_id}",
         "xml=#{xml.namespace.prefix}:#{xml.name} " \
         "attributes=#{xml.attributes.transform_values(&:value)}" <<
           (respond_to?(:label) ? " label=#{label}" : ''),
         'config=[',
         *config.map(&:inspect),
         ']>'].join("\n#{OFFSET * (@depth + 1)}")
      end

      def oneliner?
        # don't use "/flag" as xsd manipulation automatically add "xsd:" prefix
        @oneliner ||= !xml.xpath('./xsd:annotation/xsd:appinfo/*[local-name()="flag" and text()="oneliner"]').empty?
      end

      private

      def nokeyword?
        # don't use "/flag" as xsd manipulation automatically add "xsd:" prefix
        @nokeyword ||= !xml.xpath('./xsd:annotation/xsd:appinfo/*[local-name()="flag" and text()="nokeyword"]').empty?
      end

      def has_single_child_of?(klass) # rubocop:disable Naming/PredicatePrefix
        config.size == 1 && config.first.is_a?(klass)
      end

      def fmt(header, content = nil, footer = nil)
        str = (OFFSET * @depth) << header.to_s
        str << "\n" << content if content
        str << "\n" << (OFFSET * @depth) << footer if footer
        str
      end
    end
  end
end
