#!/usr/bin/env ruby

$:.unshift File.expand_path("../../lib", __FILE__)

require "neovim"
require "pathname"

vim_docs = []
buffer_docs = []
window_docs = []
tabpage_docs = []
session = Neovim::Session.child(%w(nvim -u NONE -n))
vim_defs = Neovim::Client.instance_methods(false)
buffer_defs = Neovim::Buffer.instance_methods(false)
tabpage_defs = Neovim::Tabpage.instance_methods(false)
window_defs = Neovim::Window.instance_methods(false)

session.request(:vim_get_api_info)[1]["functions"].each do |func|
  prefix, method_name = func["name"].split("_", 2)

  case prefix
  when "vim"
    next if vim_defs.include?(method_name.to_sym)
  when "buffer"
    next if buffer_defs.include?(method_name.to_sym)
  when "tabpage"
    next if tabpage_defs.include?(method_name.to_sym)
  when "window"
    next if window_defs.include?(method_name.to_sym)
  end

  return_type = func["return_type"]
  params = func["parameters"]
  params.shift unless prefix == "vim"
  param_names = params.map(&:last)
  param_str = params.empty? ? "" : "(#{param_names.join(", ")})"
  method_decl = "@method #{method_name}#{param_str}"
  method_desc = "  Send the +#{prefix}_#{method_name}+ RPC to +nvim+"
  param_docs = params.map do |type, name|
    "  @param [#{type}] #{name}"
  end
  return_doc = "  @return [#{return_type}]\n"
  method_doc = [method_decl, method_desc, *param_docs, return_doc].join("\n")
  method_doc.gsub!(/ArrayOf\((\w+)[^)]*\)/, 'Array<\1>')
  method_doc.gsub!(/Integer/, "Fixnum")

  case prefix
  when "vim"
    vim_docs << method_doc
  when "buffer"
    buffer_docs << method_doc
  when "tabpage"
    tabpage_docs << method_doc
  when "window"
    window_docs << method_doc
  end
end

lib_dir = Pathname.new(File.expand_path("../../lib/neovim", __FILE__))
{
  "client.rb" => vim_docs,
  "buffer.rb" => buffer_docs,
  "tabpage.rb" => tabpage_docs,
  "window.rb" => window_docs,
}.each do |filename, docs|
  path = lib_dir.join(filename)
  contents = File.read(path)
  doc_str = ["=begin", *docs, "=end"].join("\n")

  File.write(path, contents.sub(/=begin.+=end/m, doc_str))
end
