from irc import irc
import os
import cPickle as pickle
import re
import string

if not os.path.exists("memory"):
	os.makedirs("memory")
FILENAME = os.path.dirname(os.path.abspath(__file__)) + "\\memory\\people.txt"
# knownPeople = {}
# botAdmins = []

# Do not create a person unless you are already connected to a server
class Person(object):
	def __init__(self, nick):
		global knownPeople
		self.__nickname = nick # Prevents the setter method from being called
		self.username = nick
		self.realname = nick
		self.channels = {}
		# Find this person's username and realname
		# (If we can't, just assume it's the same as their nickname)
		irc.send('WHOIS ' + nick)
		lines = irc.grabMsg(
			returnCondition = lambda msg, searchNick=nick:
				msg.type == 'NUMERIC'
				and msg.subject in ['RPL_WHOISUSER', 'RPL_WHOISCHANNELS']
				and msg.content.partition(' ')[0] == searchNick,
			excludeCondition = lambda msg, searchNick=nick:
				msg.type == 'NUMERIC'
				and (msg.subject.startswith('RPL_WHOIS') or msg.subject in ['RPL_ENDOFWHOIS', 'ERR_NOSUCHNICK'])
				and msg.content.partition(' ')[0] == searchNick,
			abortCondition = lambda msg, searchNick=nick:
				msg.type == 'NUMERIC'
				and msg.subject in ['ERR_NOSUCHNICK', 'RPL_ENDOFWHOIS']
				and msg.content.partition(' ')[0] == searchNick,
			waitForAbortCondition=True)
		for msg in lines:
			if msg.type == 'NUMERIC':
				if msg.subject == 'RPL_WHOISUSER':
					self.username = msg.content.partition(' ')[2].partition(' * :')[0].replace(' ', '@', 1)
					self.realname = msg.content.partition(' * :')[2]
				elif msg.subject == 'RPL_WHOISCHANNELS':
					for userChannel in msg.content.partition(':')[2].split():
						if userChannel[0] != '#':
							self.channels[userChannel[1:]] = userChannel[0]
						else:
							self.channels[userChannel] = '' # todo: maybe use a unique identifier for no mod/admin?
				elif msg.subject == 'ERR_NOSUCHNICK':
					print "Error retrieving details for " + nick
					return # Assuming the caller didn't put this in a list or variable or something, the object should disappear now
		# If there's someone else we know who just has a different nickname, merge with them
		for person in knownPeople:
			if self.realname == person.realname and self.username == person.username:
				print "%s already exists; merging with %s" % (nick, person.nickname)
				onlinePeople[nick] = person
				if len(re.findall("[^%s]" % (string.ascii_letters), person.nickname)) >= len(re.findall("[^%s]" % (string.ascii_letters), nick)):
					person.__nickname = nick
				person.channels = self.channels
				return # Assuming the caller didn't put this in a list or variable or something, the object should disappear now
		onlinePeople[nick] = self
		knownPeople.append(self)
		self.botAdmin = False
	@property
	def botAdmin(self):
		return self.__botAdmin
	@botAdmin.setter
	def botAdmin(self, botAdmin):
		self.__botAdmin = botAdmin
		if botAdmin and self in botAdmins:
			botAdmins.append(self)
		elif (not botAdmin) and self in botAdmins:
			botAdmins.remove(self)
	@property
	def nickname(self):
		return self.__nickname
	@nickname.setter
	def nickname(self, nickname):
		if self in onlinePeople:
			if onlinePeople[nickname]:
				print "ERROR: %s changed their name to %s, but there is already a user nicknamed %s." % (self.__nickname, nickname, nickname)
		onlinePeople[nickname] = onlinePeople.pop(self.__nickname)
		self.__nickname = nickname

def load():
	global botAdmins, knownPeople, onlinePeople
	botAdmins = []
	onlinePeople = {}
	try:
		peopleFile = open(FILENAME, 'r')
		knownPeople = pickle.load(peopleFile)
		peopleFile.close()
	except (IOError, EOFError):
		print "WARNING: People file is empty, does not exist, or is not able to be unpickled"
	for person in knownPeople:
		person.channels = []
		if person.botAdmin:
			botAdmins.append(person)

load()

def save():
	global botAdmins
	botAdmins = []
	peopleFile = open(FILENAME, 'w')
	pickle.dump(knownPeople, peopleFile)
	print "Everyone has been serialized and saved"
	peopleFile.close()
