#!/usr/bin/python
"""
Demo implementation of a xesam server. Run it like

	demo/xesam-yahoo-service

And launch a search on it via

	./xesam-tool search -Phit.fields="xesam:title,xesam:description" hello

This is a special kind of server (ShortLivedSearcher) that will
exit after 10 secs of inactivity (if there are no sessions registered)
"""


import demo
import xesam
import xesam.query
from xesam.server import *


import gobject
import urllib
import xml.dom.minidom
from Queue import Queue
from Queue import Empty
import threading

YAHOO_API_KEY = 'uvUxFS3V34EpTiDd0ZtPXwwuJZbARPl379z7FM4Lp8MyDxYUQwQt1YhARJtJb1X0VcTZALjI'
YAHOO_URL = 'http://api.search.yahoo.com/WebSearchService/V1/webSearch?%s'
MAX_QUERIES = 10
QUERY_DELAY = 1

#
# The Yahoo Result element contains the following metadata
#
# Title
# Summary
# Url
# ClickUrl
# DisplayUrl
# ModificationDate
# MimeType
#


class YahooSearchServer (xesam.server.ShortLivedSearcher):
	"""
		
	"""
	
	def __init__ (self):
		h_fact = HandleFactory ()
		fact = ClientFactory (self, h_fact, Session, YahooSearch)
		xesam.server.ShortLivedSearcher.__init__ (self, h_fact, fact)
		
		self.TIMEOUT=10000

	
class YahooSearch (Search, threading.Thread):
	"""
		
	"""
	
	# This is the list of know fields which can be set though the
	# session property hit.fields.
	FIELDS = \
	{
		"xesam:title"		: lambda r : r.getElementsByTagName("Title")[0].firstChild.data.encode('utf8'),
		"xesam:summary"	: lambda r : r.getElementsByTagName("Summary")[0].firstChild.data.encode('utf8'),
		"xesam:mimeType"	: lambda r : r.getElementsByTagName("MimeType")[0].firstChild.data.encode('utf8'),
		"xesam:contentModified"		: lambda r : r.getElementsByTagName("ModificationDate")[0].firstChild.data.encode('utf8'),
		"yahoo:displayUrl"		: lambda r : r.getElementsByTagName("DisplayUrl")[0].firstChild.data.encode('utf8'),
		"xesam:url"	: lambda r : r.getElementsByTagName("ClickUrl")[0].firstChild.data.encode('utf8'), 
	}
	
	def __init__ (self, searcher, session, search_handle, query=None, xml=None) :
		Search.__init__ (self, searcher, session, search_handle, query=query, xml=xml)
		threading.Thread.__init__ (self)
		
		self._hit_fields = session.get_property (xesam.SESSION_HIT_FIELDS)
		if self._hit_fields is None: self._hit_fields = []
		
		self._may_run = True
		
		for field in self._hit_fields :
			if not self.FIELDS.has_key (field):
				raise UnknownFieldException (field)
		self._hit_fields
		
		if not isinstance(self.get_query(), xesam.query.UserQuery):
			raise Exception ("Only UserQuery supported ATM, sorry.")
	
	def start (self):
		threading.Thread.start (self)
	
	def run (self):
		xesam.debug ("Query yahoo for: %s" % self.get_query().get_string())
		stream = urllib.urlopen(
			YAHOO_URL % 
			urllib.urlencode(
				{'appid': YAHOO_API_KEY,
				'query': self.get_query().get_string(),
				'results': 50}))
		dom = xml.dom.minidom.parse(stream)
		
		count = 0
		for r in dom.getElementsByTagName("Result"):
			data = []
			for field in self._hit_fields:
				try:
					value = str(self.FIELDS[field](r))
				except Exception, e:
					# It appears that there are empty Summaries every
					# once in a while, so we try to hint the error
					value = str(e.__class__)
				data.append (value)
			self.add_new_hit (self._hit_fields, data)
			count += 1
		
		self.emit ("hits-added", count)
		xesam.debug ("Parsed response, found %s hits" % count)

if __name__ == "__main__":
	YahooSearchServer().start()
	
