require "pathname"
require "set"
require "json"

def resolve_path(bp, p)
  path = nil
  if bp.start_with? "."
    path = Pathname.new(File.join(bp, p)).cleanpath.to_s
  elsif p.start_with? "blog/"
    path = File.join("content", p)
  else
    path = File.join("content", "blog", p)
  end
  if File.directory? path
    path = File.join(path, "index.md") 
  elsif !path.end_with? ".md"
    path += ".md"
  end
  path.gsub("blog/blog/", "blog/")
end

files = Set.new
refs = {}
Dir['content/blog/**/*.md'].each do |file|
  file = file.chomp
  files << file
  arr = refs[file] || (refs[file] = [])
  pattern = Regexp.union(/< relref "([^"]+)" >/, /< draftlink "[^"]+" "([^"]+)" >/)
  File.open(file).read.scan(pattern) do |ref|
    ref = resolve_path(File.dirname(file), ref[0] || ref[1])
    arr << ref
    files << ref
  end
  arr.uniq!
end

data = {}
id = 0
series = {}
files.each do |file|
  id += 1
  name = file
  tags = []
  group = 1
  draft = false
  next unless File.exist?(file)
  value = File.size(file)
  url = file.gsub(/^content/, "https://danilafe.com").delete_suffix("/index.md").delete_suffix(".md")
  File.readlines(file).each do |l|
    if l =~ /^title: (.+)$/
      name = $~[1].delete_prefix('"').delete_suffix('"')
    elsif l =~ /^draft: true$/
      draft = true
    elsif l =~ /^series: (.+)$/
      this_series = $~[1]
      series_list = series.fetch(this_series) do
        series[this_series] = []
      end
      series_list << file
    elsif l =~ /^tags: (.+)$/
      tags = $~[1].delete_prefix("[").delete_suffix("]").split(/,\s?/).map { |it| it.gsub('"', '') }
      if tags.include? "Compilers"
        group = 2
      elsif tags.include? "Coq"
        group = 3
      elsif tags.include? "Programming Languages"
        group = 4
      elsif tags.include? "Haskell"
        group = 5
      elsif tags.include? "Crystal"
        group = 6
      elsif tags.include? "Agda"
        group = 7
      elsif tags.include? "Hugo"
        group = 8
      end
    end
  end
  next if draft
  data[file] = { :id => id, :name => name, :group => group, :tags => tags, :url => url, :value => value }
end

edges = []
files.each do |file1|
  # files.each do |file2|
  #   next if file1 == file2
  #   next unless data[file1][:tags].any? { |t| data[file2][:tags].include? t }
  #   edges << { :from => data[file1][:id], :to => data[file2][:id] }
  # end
  next unless frefs = refs[file1]
  frefs.each do |ref|
    next unless data[file1]
    next unless data[ref]
    edges << { :from => data[file1][:id], :to => data[ref][:id] }
  end
end
series.each do |series, files|
  files.sort.each_cons(2) do |file1, file2|
    next unless data[file1]
    next unless data[file2]
    edges << { :from => data[file1][:id], :to => data[file2][:id] }
    edges << { :from => data[file2][:id], :to => data[file1][:id] }
  end
end
edges.uniq!
# edges.filter! { |e| e[:from] < e[:to] }
edges.map! { |e| { :from => [e[:from], e[:to]].min, :to => [e[:from], e[:to]].max } }.uniq!

puts ("export const nodes = " + JSON.pretty_unparse(data.values) + ";")
puts ("export const edges = " + JSON.pretty_unparse(edges) + ";")
