require 'phi'
require 'observer'

module ApRBBR

  class BrowseList < Phi::ListView

    # これで合ってるかなあ
    unless ApRBBR.const_defined?(:GLOBAL_CONSTS)
      moduls = []
      ObjectSpace.each_object(Module) do |modul|
	moduls.push(modul)
      end
      GLOBAL_CONSTS = Object.constants - moduls
    end
    
    unless BrowseList.const_defined?(:PUBLIC_METHOD)
      PUBLIC_METHOD = 1
      PRIVATE_METHOD = 2
      PROTECTED_METHOD = 3
      SINGLETON_METHOD = 4
      CONSTANT = 5
      GLOBAL_CONSTANT = 6

      KIND2MARK = {
	PUBLIC_METHOD => '#',
	PRIVATE_METHOD => '#',
	PROTECTED_METHOD => '#',
	SINGLETON_METHOD => '.',
	CONSTANT => '::',
	GLOBAL_CONSTANT => '::',
      }
    end

    include Observable

    def initialize(form, com_name)
      super(form, com_name)
      @msg = ApRBBR.Message
      self.align = Phi::AL_CLIENT
      self.read_only = true
      self.view_style = Phi::VS_REPORT

      new_column = self.columns.add
      new_column.caption = @msg['name']
      new_column.width = 150
      new_column = self.columns.add
      new_column.caption = @msg['value']
      new_column.width = 350
      @showing_modul_name = ''
      @showing_func_name = ''
      @showing_func_kind = nil

      self.on_dbl_click = proc do
	unless self.selected.nil?
	  name = selected.caption
	  kind = selected.data
	  if (@showing_func_name != name) and
	      (@msg['public_methods'] != name) and
	      (@msg['protected_methods'] != name) and
	      (@msg['private_methods'] != name) and
	      (@msg['singleton_methods'] != name) and
	      (@msg['contants'] != name) and
	      name != ''

	    if $DEBUG
	      p kind
	      p name
	    end

	    if @showing_func_name
	      changed
	      notify_observers([@showing_modul_name, name, kind])
	      @showing_func_name = name
	      @showing_func_kind = kind
	    end

	  end
	end
      end

    end

    def update(modul)
      @showing_modul_name = modul.name
      self.items.update do 
	self.items.clear
	self.append([@msg['public_methods'], ''])
	set_PublicInstanceMethods(modul)
	self.append(['', ''])
	self.append([@msg['protected_methods'], ''])
	set_ProtectedInstanceMethods(modul)
	self.append(['', ''])
	self.append([@msg['private_methods'], ''])
	set_PrivateInstanceMethods(modul)
	self.append(['', ''])
	self.append([@msg['singleton_methods'], ''])
	set_SingletonMethods(modul)
	self.append(['', ''])
	self.append([@msg['contants'], ''])
	set_Constants(modul)
      end
    end

    def append(arr)
      unless arr.size == 2
	return false
      end

      new_item = self.items.add
      new_item.caption = arr[0]
      new_item.sub_items.add(arr[1])

      new_item
    end
    
    def set_PublicInstanceMethods(modul)
      modul.public_instance_methods.sort.each do |name|
	item = self.append([name, modul.instance_method(name).arity.to_s])
	item.data = PUBLIC_METHOD
      end
    end

    def set_ProtectedInstanceMethods(modul)
      modul.protected_instance_methods.sort.each do |name|
	item = self.append([name, modul.instance_method(name).arity.to_s])
	item.data = PROTECTED_METHOD
      end
    end

    def set_PrivateInstanceMethods(modul) 
      modul.private_instance_methods.sort.each do |name|
	item = self.append([name, modul.instance_method(name).arity.to_s])
	item.data = PRIVATE_METHOD
      end
    end

    def set_SingletonMethods(modul) 
      modul.singleton_methods.sort.each do |name|
	item = self.append([name, modul.method(name).arity.to_s])
	item.data = SINGLETON_METHOD
      end
    end

    def set_Constants(modul)
      modul.true_constants.sort.each do |name|
	item = self.append([name, modul.const_get(name).inspect])
	if global_constant?(name)
	  item.data = GLOBAL_CONSTANT
	else
	  item.data = CONSTANT
	end
      end
    end

    def global_constant?(name)
      if GLOBAL_CONSTS.include?(name)
	return true
      else
	return false
      end
    end

  end


end
