# frozen_string_literal: true

module Infoboxer
  module Tree
    # Base class for all nodes with children.
    class Compound < Node
      def initialize(children = Nodes.new, **params)
        super(**params)
        @children = Nodes[*children]
        @children.each { |c| c.parent = self }
      end

      # List of children
      #
      # @return {Nodes}
      attr_reader :children

      # Index of provided node in children list
      #
      # @return [Fixnum] or `nil` if not a child
      def index_of(child)
        children.index(child)
      end

      # @private
      # Internal, used by {Parser}
      def push_children(*nodes)
        nodes.each { |c| c.parent = self }.each do |n|
          @children << n
        end
      end

      # See {Node#text}
      def text
        children.map(&:text).join(children_separator)
      end

      # See {Node#to_tree}
      def to_tree(level = 0)
        if children.count == 1 && children.first.is_a?(Text)
          "#{indent(level)}#{children.first.text} <#{descr}>\n"
        else
          "#{indent(level)}<#{descr}>\n" + children.map { |c| c.to_tree(level + 1) }.join
        end
      end

      # Kinda "private" methods, used by Parser only -------------------

      # @private
      # Internal, used by {Parser}
      def can_merge?(_other)
        false
      end

      # @private
      # Internal, used by {Parser}
      def closed!
        @closed = true
      end

      # @private
      # Internal, used by {Parser}
      def closed?
        @closed
      end

      # @private
      # Internal, used by {Parser}
      def empty?
        children.empty?
      end

      protected

      def children_separator
        ''
      end

      private

      def _eq(other)
        children == other.children
      end
    end
  end
end
