#! /usr/bin/env ruby

# for each version directory, sorted alphabetically, nothing that 'unreleased'
# comes before 'v1.2.3'

versions = ['changelog.d/unreleased'] + Dir['changelog.d/v*'].sort.reverse

category_titles = {
  'breaking' => "Breaking",
  'enhancement' => "Enhancements",
  "fix" => "Fixes",
  "minor" => "Minor"
}

# print out static header
File.foreach('changelog.d/header.md') do |line|
  puts line
end
puts()

# print out changelog header for this version
versions.each do |version_dir|

  next unless File.directory?(version_dir)

  header_path = "#{version_dir}-header.md"
  version_name = File.basename(version_dir)

  puts("## #{version_name}")
  puts()


  if version_name == 'unreleased'
    puts("*Not yet released*")
    puts("")
  elsif File.exist?(header_path)
    puts()
    puts(File.read(header_path).strip())
    puts()
  else
    STDERR.puts("Missing version header - #{header_path}")
    exit 1
  end

  # for each change category (breaking, enhancement, fix, minor)
  categories = %w{breaking enhancement fix minor}

  # validate files in dir to make sure noone's typod the prefix
  Dir[version_dir + "/*.md"].each do |path|
    if ! categories.any? {|cat| File.basename(path).start_with?("#{cat}-") }
      STDERR.puts("Misnamed file? #{path}")
      exit 1
    end
  end

  categories.each do |category|
    fragments = Dir["#{version_dir}/#{category}-*.md"]

    next if fragments.empty?

    puts("### #{category_titles[category]}")
    puts("")

    fragments.sort.each do |fragment_file|
      fragment = File.read(fragment_file).strip

      unless fragment.start_with?('-')
        lines = fragment.split("\n")
        lines = lines.map.with_index do |line, idx|
          if idx == 0 && line.match(/^[^ -]/)
            "- " + line
          else
            "  " + line
          end
        end

        fragment = lines.join("\n")
      end

      puts(fragment)
      puts()
    end

  end
end

# print out footer - this contains the changelog before
# this script existed
File.foreach('changelog.d/footer.md') do |line|
  puts line
end
