#!/usr/bin/python

import sys
from os.path import dirname,join,abspath,exists
import gobject

# Check if we are running uninstalled
parent_dir = dirname(__file__)
if exists(join(parent_dir, "MANIFEST.in")):
	print >> sys.stderr, ("Running uninstalled. Adding to Python path: " + abspath(parent_dir))
	sys.path.insert(0, abspath(parent_dir))
	
import xesam
import xesam.client

class SearchTask :
	def __init__ (self, task_args):
		self.session = xesam.client.Session()
		xesam.debug("Got session handle:" + self.session.get_handle())
		
		self.search_string = ""
		self._engine = None
		
		for arg in task_args:
			if arg.startswith("-") :
				if arg.startswith("-P") :
					prop, val = tuple(arg[2:].split("="))
					val = xesam.prop_val(prop, val) # translate value to correct type
					xesam.debug ("Setting property: %s=%s" % (prop, val))
					self.session.set_property (prop, val)
				elif arg == "-s" or arg == "--state-messages":
					self._engine = xesam.client.EngineState()
					self._engine.connect ("changed", self.on_engine_state_changed)
					xesam.debug ("Engine state is [%s, %s]" % (self._engine.get_state(), self._engine.get_value()))
			else:
				# Concatenate the rest of the args into the search string
				self.search_string = " ".join(task_args[task_args.index(arg):])
				break

		self.hit_fields = self.session.get_property ("hit.fields")
		if self.hit_fields is None : self.hit_fields = []
		
		self.hit_fields_ext = self.session.get_property ("hit.fields.extended")
		if self.hit_fields_ext is None: self.hit_fields_ext = []
		
		self.search = None
		self.search_class = xesam.client.UserSearch
		self.mainloop = gobject.MainLoop()
	
	def run (self):
		self.search = self.search_class (self.session, self.search_string)
		self.search.connect ("hits-added", self.on_hits_added)
		self.search.connect ("hits-removed", self.on_hits_removed)
		self.search.connect ("hits-modified", self.on_hits_modified)
		self.search.connect ("done", self.on_search_done)
		
		# Start search and listen for events
		gobject.idle_add(self.search.start)
		try:
			self.mainloop.run()
		except KeyboardInterrupt:
			# Exit cleanly if we are ctrl-c'ed
			xesam.debug ("Caught keyboard interrupt. Closing session.")
			self.session.close()
	
	def on_hits_added (self, search, count):
		hits = self.search.get_hits(count)
		for hit in hits:
			print "HitAdded: " + unicode(hit) + "\n"

	def on_hits_removed (self, search, hit_ids):
		for hit_id in hit_ids:	
			print "HitRemoved", str(hit_id)

	def on_hits_modified (self, search, hit_ids):
		# We collect the extended fields on modified hits - just for kicks
		hits = self.search.get_hit_data_from_ids (hit_ids, self.hit_fields_ext)
		for hit in hits:
			print "HitModified:", str(hit)
	
	def on_search_done (self, search):
		xesam.debug ("Search '%s' done. Got %s hits" % (search.get_handle(), search.get_hit_count()))
	
	def on_engine_state_changed (self, engine, state_info):
		xesam.debug ("Engine state changed: %s" % state_info)

class QueryTask (SearchTask):
	def __init__ (self, task_args):
		SearchTask.__init__ (self, task_args)
		# The self.search_string will actually be a file
		# path in this case. Read the file in.
		if self.search_string.strip() == "":
			self.search_string = "".join(sys.stdin.readlines())
		else:
			self.search_string = "".join(file(self.search_string).readlines())
		
		# Override the default search object
		self.search_class = xesam.client.Search
		
	

class HelpTask :
	def __init__ (self, task_args):
		pass
	
	def run (self):
		print "USAGE:\n\t%s <task>\n" % (sys.argv[0])
		print "Possible tasks:"
		for t in TASKS.iterkeys():
			print "\t%s %s" % (t, TASKS[t]["description"])
		

TASKS = {
	"search" : {
					"class" : SearchTask,
					"description" : "[-P<property>=<value>] [-s|--state-messages] <search terms>",
				},
	"query" : {
					"class" : QueryTask,
					"description" : "[-P<property>=<value>] [-s|--state-messages] [query source file or empty for stdin]",
				},
	"help"	 : {
					"class" : HelpTask,
					"description" : "(display this message)",
				},
}

#
# Actual program starts here
#

if len(sys.argv) <= 1 :
	task = "help"
else:
	task = sys.argv[1]
	
if not TASKS.has_key(task):
	xesam.error("Unknown task '%s'" %  task)
	task = "help"
	
task = TASKS[task]["class"](sys.argv[2:]) # instantiate the appropriate task object
task.run()
