#!/usr/bin/python
#todo:
#header ""

import toc
from toc import TocTalk, BotManager
import httplib
import string
import sys, traceback
import time
from xreadlines import xreadlines
from urllib import urlencode
import random

BOT_SCREENNAME = "A" #SET THIS
BOT_PASSWORD = "a" #SET THIS
TIME_SINCE_UP = 0
#Sorry, I don't understand.  I'm just a bot.
SYNTAX = """send me a number to get that haiku (0 for the latest)
"random" to get a random haiku
"comments" to see the latest comment - "comments n" to get comment n
"link" to get a random link from my list of random links
"search" to search for a haiku
"help" to see this message - "help <command>" to get info on that command
"""
CMDHELP = {}
CMDHELP["random"] = "displays a random haiku.  Arguments are ignored."
CMDHELP["comments"] = "read the latest comment.  With a numerical argument, read that comment"
CMDHELP["link"] = "show a random link from an esoteric list.  email me if you'd like a link added"
CMDHELP["help"] = "you're lookin' at it"
CMDHELP["search"] = """search [{index}] [{field}] {terms}
index defaults to 1, field defaults to all.
Due to message length limitations, only one haiku can be sent per search result, so index scrolls through the results.
field can be first, second, third, or author"""

HEADER = """Brought to you by http://haiku.fuzrocks.com\n"""

LINKS = []
LINKCOUNT = 0
linkfile = open("links.txt")
for line in xreadlines(linkfile):
	LINKS.append(line[:len(line)-1])
	LINKCOUNT = LINKCOUNT+1

def is_int(var):
	try:
		return int(var)
	except(ValueError):
		return -1

def strlist(terms):
	try:
		out = terms[0]
		for term in terms[1:]:
			out = out + " " + term
		return out
	except:
		print "strlist exception"
		return ""
	
class IMSyntaxError(Exception):
	def __init__(self, value):
		self.value = value
	def __str__(self):
		return repr(self.value)
	
	
class HaikuBot(TocTalk):
	"""haiku fetcher"""
	def __init__(self,uname,password):
		TocTalk.__init__(self,uname,password)
	
	def on_IM_IN(self, data):
		screenname, flag, omessage = data.split(":",2)
		message = self.strip_html(omessage)
		mess_comps = message.split(" ",1)
		cmd = mess_comps[0]
		h = httplib.HTTPConnection("haiku.fuzrocks.com")
		r=0 #reply
		print "%s said %s" % (screenname, message)
		sys.stdout.flush()
	
		if screenname == BOT_SCREENNAME:
			TIME_SINCE_UP = 0
			return
	
		index = is_int(cmd)
		if index >= 0:
			try:
				h.request("GET", "/bot.html?action=index&index=%s" % index)
				r = h.getresponse().read()
			except:
				r = "Sorry, I failed in my connection to the haiku server!  Please try again."
		else:
			if cmd == "search":
				try:
					if len(mess_comps) < 2: #cmd was "search"
						raise IMSyntaxError("you need to search for something\n" + SYNTAX)
					args = mess_comps[1]
					arg_comps = args.split(" ")
					validfields = ["first", "second", "third", "author", "all"]
					if is_int(arg_comps[0]) >= 0 and len(arg_comps) > 1: #len filters out "search <num>, which should search for the number
						skip = arg_comps[0]
						#print "ac:"
						#print arg_comps
						#print "ac[2:]" 
						#print arg_comps[2:]
						if arg_comps[1] in validfields and len(arg_comps) > 2: #len filters out search <num> <column>, which should get the <num>th entry for column
							#this is search <num> <column> <term>
							termstring = strlist(arg_comps[2:])
							#print "termstring: " + termstring
							terms = urlencode({"term":termstring})
							#print "term: " + terms
							req = "/bot.html?action=search&skip=%s&column=%s&%s" % (skip, arg_comps[1], terms)
							#print "num column req:"
							#print req
							try:
								h.request("GET", req)
								r = h.getresponse().read()
							except:
								r = "Sorry, I failed in my connection to the haiku server!  Please try again."
						else:
							#this is search <num> <stuff>, and <stuff> is not being read as a column
							req = "/bot.html?action=search&skip=%s&%s" % (skip, urlencode({"term":strlist(arg_comps[1:])}))
							#print "num only req:"
							#print req
							try:
								h.request("GET", req)
								r = h.getresponse().read()
							except:
								r = "Sorry, I failed in my connection to the haiku server!  Please try again."
					elif arg_comps[0] in validfields and len(arg_comps) > 1:
						#first isn't number, is column
						req = "/bot.html?action=search&column=%s&%s" % (arg_comps[0], urlencode({"term":strlist(arg_comps[1:])}))
						try:
							h.request("GET", req)
							r = h.getresponse().read()
						except:
							r = "Sorry, I failed in my connection to the haiku server!  Please try again."
					else:
						#first isn't either number or column
						try:
							h.request("GET", "/bot.html?action=search&%s" % (urlencode({"term" : args})))
							r = h.getresponse().read()
						except:
							r = "Sorry, I failed in my connection to the haiku server!  Please try again."
				except IMSyntaxError:
					r = SYNTAX
			elif cmd == "random":
				try:
					h.request("GET", "/bot.html?action=random")
					r = h.getresponse().read()
				except:
					r = "Sorry, I failed in my connection to the haiku server!  Please try again."
			elif cmd == "ip":
				try:
					h.request("GET", "/ip.html")
					r = h.getresponse().read()
				except:
					r = "Sorry, I failed in my connection to the haiku server!  Please try again."
			elif cmd == "comments":
				if(len(mess_comps) < 2):
					try:
						h.request("GET", "/bot.html?action=comments")
						r = h.getresponse().read()
					except:
						r = "Sorry, I failed in my connection to the haiku server!  Please try again."
				else:
					argstring = mess_comps[1]
					args = argstring.split(" ")
					index = is_int(args[0])
					if(index < 0):
						try:
							h.request("GET", "/bot.html?action=comments")
							r = h.getresponse().read()
						except:
							r = "Sorry, I failed in my connection to the haiku server!  Please try again."
					else:
						#print "index: |%d|" % index
						req = "/bot.html?action=comments&index=%i" % index
						#print "req: " + req
						try:
							h.request("GET", req)
							r = h.getresponse().read()
						except:
							r = "Sorry, I failed in my connection to the haiku server!  Please try again."						
			elif cmd == "help":
				if(len(mess_comps) < 2):
					r = SYNTAX
				else:
					argstring = mess_comps[1]
					args = argstring.split(" ")
					if(CMDHELP.has_key(args[0])):
						r = CMDHELP[args[0]]
					else:
						r = ("There is no help for %s\n" % args[0]) + SYNTAX
			elif cmd == "link":
				rnd = random.randrange(0, LINKCOUNT, 1)
				r = LINKS[rnd]
			else:
				r = SYNTAX
		
		screenname, rest = data.split(":",1)
		target = self.normalize(screenname)
		try:
			self.do_SEND_IM(target, HEADER + r)
		except(toc.TOCError):
			self.do_SEND_IM(target, "Something went wrong while trying to reply.  Please inform fuz what you told me")

def on_err(err, tb):
	print err[0]
	print err[1]
	print err[2]
	outtb = ""
	for line in tb:
		outtb = outtb + line;
	print outtb
	sys.stdout.flush()
	return
			
if __name__ == "__main__":
	while(1):
		TIME_SINCE_UP = 600
		try:
			if(TIME_SINCE_UP > 320):
				try:
					bot._socket.close()
				except:
					pass
				try:
					bot = HaikuBot(BOT_SCREENNAME, BOT_PASSWORD)
					bot._debug = 0
					bot._info = HEADER
					bot.go()
				except:
					TIME_SINCE_UP=600
					#err = sys.exc_info()[1]
					err = sys.exc_info()
					tb = traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback, 20)
					on_err(err, tb)

			time.sleep(60) #sleep for one minute
			TIME_SINCE_UP = TIME_SINCE_UP + 60
		except:
			err = sys.exc_info()
			tb = traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback, 20)
			on_err(err, tb)
			TIME_SINCE_UP=600

