module Rack
  class ReverseProxyMatcher
    def initialize(matcher,url=nil,options)
      @default_url=url
      @url=url
      @options=options

      if matcher.kind_of?(String)
        @matcher = /^#{matcher.to_s}/
      elsif matcher.respond_to?(:match)
        @matcher = matcher
      else
        raise "Invalid Matcher for reverse_proxy"
      end
    end

    attr_reader :matcher,:url, :default_url,:options

    def match?(path, *args)
      match_path(path, *args) ? true : false
    end

    def get_uri(path,env)
      return nil if url.nil?
      _url=(url.respond_to?(:call) ? url.call(env) : url.clone)
      if _url =~/\$\d/
        match_path(path).to_a.each_with_index { |m, i| _url.gsub!("$#{i.to_s}", m) }
        URI(_url)
      else
        default_url.nil? ? URI.parse(_url) : URI.join(_url, path)
      end
    end

    def to_s
      %Q("#{matcher.to_s}" => "#{url}")
    end

    private
    def match_path(path, *args)
      headers = args[0]
      rackreq = args[1]
      arity = matcher.method(:match).arity
      if arity == -1
        match = matcher.match(path)
      else
        params = [path, (@options[:accept_headers] ? headers : nil), rackreq]
        match = matcher.match(*params[0..(arity - 1)])
      end
      @url = match.url(path) if match && default_url.nil?
      match
    end
  end
end