#!/usr/bin/env ruby
#
# rrse --- Ruby Reference|Refe Seeker for Emacsen
# 
# Copyright (C) 2006 Ohbayashi Ippei
#
# This software is distributed under GNU General Public License version 2.
#
# This file is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
require 'refe/database'
require 'refe/searcher'
require 'refe/config'
require 'optparse'

class ReFeInfo
  def initialize(datadir)
    @datadir = datadir
  end

  def descs
    db = ReFe::Database.new(@datadir)
    descs = []
    db.method_document.complete(nil, nil, '*').each do |spec|
      case spec
      when /^man\..*$/
      when /^[A-Za-z0-9_:]+(#|\.)[^#.]+$/
        descs << Description.new(spec, db.method_document[spec])
      else
        raise "invalid information"
      end
    end

    return descs
  end
  
  def display_info(reverse)
    if reverse
      descs.
        inject(Hash.new{|h,k| h[k]=[]}){|h, desc| h[desc.method] << desc.spec; h}.
        sort_by{|method, *| method}.
        each{|method, specs| puts "#{method}\t#{specs.join("\t")}"}
    else
      descs.sort_by{|desc| desc.spec}.each{|desc| puts desc.show }
    end
  end
  
  class Description
    attr_reader :spec, :method, :descs
    
    def initialize(spec, str)
      @spec = spec
      @mod, @method = spec.split(/\#|\./)
      @kind = if spec.include?("#") then :instance else :class end
      match_descline = proc do |line|
        /^#{Regexp.quote(@spec)}[ (]/ =~ line ||
          /^#{Regexp.quote(@method)}[ (]/ =~ line ||
          line.include?("self[")
      end
      
      @descs = str.
        split(/\n/).
        select{|line| /^(---|:) / =~ line}.
        map{|line| line.sub(/^(---|:) /, "")}.
        select(&match_descline).
        map{|line| if /\s*ruby 1\.. feature/ =~ line then $` else line end}.
        map{|line| if /^#{Regexp.quote(@spec)}/ =~ line then $' else line end}.
        map{|line| if /^#{Regexp.quote(@method)}/ =~ line then $' else line end}
    end

    def show
      "#{@spec}\t#{@descs.join("\t")}"
    end
  end
end

opt = OptionParser.new
datadir = nil
reverse = false
opt.on('-d DIR', 'Use DIR as the refe database root directory'){|v| datadir = v}
opt.on('-r', 'Print reverse data'){ reverse = true }
opt.parse!(ARGV)

begin
  ReFeInfo.new(datadir).display_info(reverse)
rescue RuntimeError
  raise
rescue ReFe::Error => err
  $stderr.puts err.message
  exit 1
rescue StandardError => err
  raise if $DEBUG
  $stderr.puts err.message
  exit 1
end
