require 'markdown_helper/version'

# Helper class for working with GitHub markdown.
#  Supports file inclusion.
#
# @author Burdette Lamar
class MarkdownHelper

  INCLUDE_REGEXP = /^@\[(:code_block|:verbatim|\w+)\]/

  # For later.
  # attr_accessor :tag_as_generated

  # For later.
  # DEFAULT_TREATMENT_FOR_FILE_EXT = {
  #     :md => :verbatim,
  #     :rb => 'ruby',
  #     :xml => 'xml',
  # }

  def initialize
    # For later.
    # @treatment_for_file_ext = DEFAULT_TREATMENT_FOR_FILE_EXT
    # @treatment_for_file_ext.default = :code_block
    # self.tag_as_generated = false
  end

  # Merges external files into markdown text.
  # @param template_file_path [String] the path to the input template markdown file, usually containing include pragmas.
  # @param markdown_file_path [String] the path to the output merged markdown file.
  # @raise [RuntimeError] if an include pragma parsing error occurs.
  # @return [String] the resulting markdown text.
  #
  # @example Pragma to include text as a highlighted code block.
  #   @[ruby](foo.rb)
  #
  # @example Pragma to include text as a plain code block.
  #   @[:code_block](foo.xyz)
  #
  # @example Pragma to include text verbatim, to be rendered as markdown.
  #   @[:verbatim](foo.md)
  def include(template_file_path, markdown_file_path)
    output_lines = []
    File.open(template_file_path, 'r') do |template_file|
      # For later.
      # if tag_as_generated
      #   output_lines.push("<!--- GENERATED FILE, DO NOT EDIT --->\n")
      # end
      template_file.each_line do |input_line|
        match_data = input_line.match(INCLUDE_REGEXP)
        unless match_data
          output_lines.push(input_line)
          next
        end
        treatment = case match_data[1]
                      when ':code_block'
                        :code_block
                      when ':verbatim'
                        :verbatim
                      else
                        match_data[1]
                    end
        file_path_in_parens =  input_line.sub(INCLUDE_REGEXP, '')
        unless file_path_in_parens.start_with?('(') && file_path_in_parens.end_with?(")\n")
          raise RuntimeError.new(file_path_in_parens.inspect)
        end
        relative_file_path = file_path_in_parens.sub('(', '').sub(")\n", '')
        include_file_path = File.join(
            File.dirname(template_file_path),
            relative_file_path,
        )
        included_text = File.read(include_file_path)
        unless included_text.match("\n")
          message = "Warning:  Included file has no trailing newline: #{include_file_path}"
          warn(message)
        end
        extname = File.extname(include_file_path)
        file_ext_key = extname.sub('.', '').to_sym
        treatment ||= @treatment_for_file_ext[file_ext_key]
        if treatment == :verbatim
          # Pass through unadorned.
          output_lines.push(included_text)
        else
          # Use the file name as a label.
          file_name_line = format("<code>%s</code>\n", File.basename(include_file_path))
          output_lines.push(file_name_line)
          # Put into code block.
          language = treatment == :code_block ? '' : treatment
          output_lines.push("```#{language}\n")
          output_lines.push(included_text)
          output_lines.push("```\n")
        end
      end
    end
    output = output_lines.join('')
    File.open(markdown_file_path, 'w') do |md_file|
      md_file.write(output)
    end
    output
  end

  # For later.
  # def get_treatment(file_type)
  #   @treatment_for_file_ext[file_type]
  # end
  #
  # def set_treatment(file_type, treatment)
  #   treatment_symbols = [:verbatim, :code_block]
  #   if treatment_symbols.include?(treatment) || treatment.kind_of?(String)
  #     @treatment_for_file_ext[file_type] = treatment
  #   else
  #     message = "treatment must be a single word or must be in #{treatment_symbols.inspect}, not #{treatment.inspect}"
  #     raise ArgumentError.new(message)
  #   end
  # end

end