module Willow
  # Public: Collection of common methods and accessors that read in YAML headers,
  #         parse text files, etc. For use in passing objects to the Parser class.
  #
  # Requires
  # This should be included within a Willow::Document inherited class
  #
  module Parseable

    # Public: The configured layout for this page/post
    #
    # Returns a Layout object
    def layout
      layout = (@data && @data[:layout]) || @site.config[:defaults][:layout]
      @site.layouts[layout]
    end

    # Public: Renders the page with a layout
    #
    # Returns the rendered page content
    def render
      @output = Willow::View.new(@site, @content, @site.to_hash.deep_merge(self.to_hash)).render
      unless @data[:parser] && @data[:parser] == 'none'
        @output = parser.parse(@output)
        # markdown = Redcarpet::Markdown.new(Willow::RedcarpetRenderer, _redcarpet_options)
        # @output = markdown.render(@output)
      end
      render_layouts
    rescue Exception => error
      Willow.log_error "Error rendering #{self.source_path}"
      Willow.log_error error.message
    end

    # Public: Determines the parser to use base on the extension
    #
    # Returns a Parser instance
    def parser
      @parser ||= @site.parsers.find { |p| p.matches(self.ext) }
    end

    # Public: Renders layouts recursively
    #
    # Returns the rendered output
    def render_layouts
      layout = self.layout
      used = Set.new([layout])

      while layout
        data = self.to_hash
        layout.data.deep_merge(data) if layout.data
        @output = Willow::View.new(@site, layout.content, @site.to_hash.deep_merge(data).deep_merge(content: @output)).render
        if layout = @site.layouts[layout.data[:layout]]
          if used.include?(layout)
            layout = nil
          else
            used << layout
          end
        end
      end
      @output
    end

    private

    # Private: retrieves the redcarpet options
    #
    # Returns an array of true options. False options are ignored.
    def _redcarpet_options
      @site.config[:redcarpet][:extensions].select { |k,v| v == true }
    end

  end

end
