require 'cgi'
require 'open-uri'
require 'json'

module GoogleAJAX
  class Search
    class BadResponse < RuntimeError; end
    
    API_VERSION = '1.0'
    UDS_BASE = 'http://www.google.com/uds/api?'
    UDS_PARAMS = {
      'file' => 'uds.js',
      'v' => API_VERSION
    }
    SEARCH_BASE = 'http://www.google.com/uds/GwebSearch?'
    SEARCH_PARAMS = {
      'callback' => 'f',
      'context' => 0,
      'lstkp' => 0,
      'rsz' => 'large',
      'hl' => 'en',
      'v' => API_VERSION
    }

    attr_reader :key
    attr_accessor :lang
    
    def initialize(key)
      @lang = 'en'
      @key = key
    end
    
    def search(keyword)
      parse(
        fetch(
          request_uri(
            SEARCH_BASE, 
            SEARCH_PARAMS.merge(
              'q'   => keyword,
              'key' => key, 
              'sig' => js_hash,
              'hl'  => lang
            )
          )
        )
      )
    end
    
    def request_uri(base, params)
      base + params.map{ |key, value|
        "#{key}=#{CGI.escape(value.to_s)}"
      }.join('&')
    end
    
    def fetch(uri)
      open(uri){ |io| io.read }
    end
    
    def parse(response)
      if response =~ /^f\('0', (.*), 200, null, 200\)$/
        json = $1
        p json[40,20]
        # Shameful quick and dirty hack to make it work with Ruby's JSON parser:
        json.gsub!(/([\{\}\[\],]) ?([a-z0-9]+) ?:/i){ %{#{$1} "#{$2}":} } 
        return JSON.parse(json)
      else
        raise BadResponse, "couldn't parse response"
      end
    end
    
    def js_hash
      @js_hash ||= fetch(
        request_uri(
          UDS_BASE, 
          UDS_PARAMS.merge('key' => key)
        )
      )[/var UDS_JSHash = "(.*?)"/, 1]
    end
  end
end
