#!/usr/bin/ruby -Ke
#
# mkrefe_rubyrefm.rb
#
# Copyright (c) 2003 Minero Aoki <aamine@loveruby.net>
#
# This program is free software.
# You can distribute/modify this program under the terms of
# the GNU Lesser General Public License version 2 or later.
#

require 'refe/database'
require 'refe/rubyrefmparser'
require 'refe/mygetopt'
require 'refe/info'


def parse_options
  getopt = MyGetoptLong.new(<<EndUsage, <<EndOptions)
Usage: mkrefe_rubyrefm [-d <dir>] <filename>

%%options%%

EndUsage

  o -d --databasedir  <dir>  Use <dir> as the database directory.
  o -e --extend       -      Extend completion table to support inheritance.
  o -  --version      -      Print program version and quit.
  o -h --help         -      Print this message and quit.

EndOptions

  opts = {}
  begin
    getopt.each do |name, arg|
      opts[name] = arg
    end
  rescue => err
    getopt.usage 1, err.message
  end
  getopt.usage(0) if opts['--help']
  (puts "mkrefe_extrefm version #{ReFe::Version}"; exit 0) if opts['--version']
  opts
end

def main
  opts = parse_options()
  db = ReFe::Database.new(opts['--databasedir'], true)
  update_database db, ARGV unless opts['--extend']
  extend_method_completion_table db.method_comp_file, db.inheritance_graph
end

def update_database( db, srcfiles )
  cdoc = db.class_document
  mdoc = db.method_document
  parser = ReFe::RubyReferenceManualParser.new
  srcfiles.each do |fname|
    next if reject_filename?(File.basename(fname, '.rd'))
    File.open(fname) {|f|
      classes, methods = parser.parse(f)
      classes.each do |c, doc|
        cdoc[c] = doc
        methods.each do |c, tbl|
          tbl.each do |m, doc|
            mdoc["#{c}#{m}"] = doc
          end
        end
      end
    }
  end
  cdoc.flush
  mdoc.flush
end

def reject_filename?( fname )
  return true if %r<[^\w\.\-:/]> === urldecode(fname)
  return true if /\Atrap/ === fname
  return true if /\AFAQ/ === fname
  false
end

def extend_method_completion_table( path, igraph )
  specs = read_method_specs(path)
  table = build_table(specs)
  new = []
  table.keys.each do |c|
    inherited_methods_of(c, table, igraph).each do |t_m|
      new.push "@#{c}#{t_m}"
    end
  end
  File.open(path, 'w') {|f|
    (specs + new).uniq.sort.each do |sp|
      f.puts sp
    end
  }
end

def inherited_methods_of( klass, method_table, igraph )
  a = igraph.ancestors_of(klass)
  a.shift   # remove klass itself
  a.map {|c| method_table[c] }.flatten.compact - method_table[klass]
end

def build_table( specs )
  table = {}
  specs.each do |sp|
    c, t, m = sp.sub(/\A@/, '').split(/([\.\#])/)
    (table[c] ||= []).push(t + m)
  end
  table
end

def read_method_specs( path )
  File.readlines(path).map {|line| line.strip }
end

def urldecode( str )
  str.gsub(/%[0-9a-fA-F]{2}|\+/n) {|s| s == '+' ? ' ' : s[1,2].hex.chr }
end


main
