require "hpricot"
require "fileutils"

module BridgeSupport
  class Parser
    def initialize(path_from, path_to)
      @doc = open(path_from) {|f| Hpricot(f).search('signatures').first}
      if @doc and @doc.children
        FileUtils.mkdir_p File.dirname(path_to)
        o = open(path_to, 'w')
        o.write(@doc.children.collect do |el|
          next if el.is_a?(Hpricot::Text)
          case el.name
            when 'class'    then ClassDef.new(el).write('%s/%s.rb' % [File.dirname(path_to),el.attributes['name']])
            when 'function' then FunctionDef.new(el).to_s
            when 'enum'     then ConstantDef.new(el).to_s
                            else BaseDef.new(el).to_s
          end
        end.compact.join("\n\n"))
        o.close
      end
    end
  end
  class BaseDef
    def initialize(el)
      @el = el
    end
    def to_s
      '# ' + @el.to_s.gsub("\n","\n# ")
    end
    def attr(key)
      @el.attributes[key]
    end
    def indent(str, n=2)
      n = ' '*n if n.is_a? Fixnum
      str = str.join("\n\n") if str.is_a? Array
      n + str.gsub("\n", "\n"+n)
    end
  end
  class ClassDef < BaseDef
    def to_s
      "class %s < NSObject\n%s\n\n%s\nend" % [attr('name'), indent(methods_def), indent(super)]
    end
    def methods_def
      @el.children.collect do |c|
        if c.name == 'method'
          BridgeSupport::MethodDef.new(c).to_s
        end
      end.compact
    end
    def write(path)
      FileUtils.mkdir_p(File.dirname(path))
      open(path,'w') {|f| f.write(to_s)}
    end
  end
  class FunctionDef < BaseDef
    def retval
      r = @el.search('retval').first
      "%s [ %s ]" % [r.attributes['declared_type'], r.attributes['type']]
    end
    def to_s
      "def %s(%s) # => %s\n%s\nend" % [name, args.join(', '), retval, indent(super)]
    end
    def name
      attr('name')
    end
    def args
      @el.children.collect do |c|
        c.attributes['name'] if c.name == 'arg'
      end.compact
    end
  end
  class MethodDef < FunctionDef
    def to_s
      arg = args.join(', ')
      "def self.#{name}(#{arg}) end\n%s" % super
    end
    def messages
      attr('selector')[0..-1].split(':')
    end
    def name
      messages.first
    end
    def args
      msg = messages
      arg = @el.children.collect do |c|
        c.attributes['name'] if c.name == 'arg'
      end.compact
      arg.collect.with_index do |a,i|
        if i > 0 and msg and msg[i]
          "%s:%s" % [msg[i], a]
        else
          a
        end
      end
    end
  end
  class ConstantDef < BaseDef
    def to_s
      "%s = %s\n%s" % [attr('name'), attr('value'), super]
    end
  end
end

source_dir = '/Library/RubyMotion/data/5.1/BridgeSupport'
destination_dir = '/Users/andrei/DropboxAndrei/Dropbox/Projects/iOS/BridgeSupport'
Dir[source_dir + '/*.bridgesupport'].each do |f|
  p f
  BridgeSupport::Parser.new(f, destination_dir + '/%s/framework.rb' % File.basename(f,'.bridgesupport'))
end