from MiscUtils import NoDefault
from MiscUtils.Funcs import uniqueId
import time


class User:
	"""
	@@ 2001-02-19 ce: docs
	"""


	## Init ##

	def __init__(self, manager=None, name=None, password=None):
		self._creationTime = time.time()

		self._manager = None
		self._name = None
		self._password = None
		self._isActive = 0
		self._externalId = None

		if name is not None:
			self.setName(name)
		if manager is not None:
			self.setManager(manager)
		if password is not None:
			self.setPassword(password)


	## Attributes ##

	def manager(self):
		return self._manager

	def setManager(self, manager):
		"""Set the manager, which can only be done once."""
		assert self._manager is None
		from UserManager import UserManager
		assert isinstance(manager, UserManager)
		assert manager.userForName(self.name(), None) is None, \
			'There is already a user named %r.' % self.name()
		self._manager = manager

	def serialNum(self):
		return self._serialNum

	def externalId(self):
		if self._externalId is None:
			from time import localtime, time
			attempts = 0
			while attempts<10000:
				self._externalId = uniqueId(self)
				# @@ 2001-02-17 ce: check that manager doesn't already have this
				# if mgr.userForExternalId(self._externalId, None) is None:
				#	break
				break
				attempts += 1
			else:
				raise Exception, "Can't create valid external id after %i attempts." % attempts
		return self._externalId

	def name(self):
		return self._name

	def setName(self, name):
		"""Set the name, which can only be done once."""
		assert self._name is None
		self._name = name
		# @@ 2001-02-15 ce: do we need to notify the manager
		# which may have us keyed by name?

	def password(self):
		return self._password

	def setPassword(self, password):
		self._password = password
		# @@ 2001-02-15 ce: should we make some attempt to
		# cryptify the password so it's not real obvious
		# when inspecting memory?

	def isActive(self):
		return self._isActive

	def creationTime(self):
		return self._creationTime

	def lastAccessTime(self):
		return self._lastAccessTime

	def lastLoginTime(self):
		return self._lastLoginTime


	## Log in and out ##

	def login(self, password, fromMgr=0):
		"""Return self if the login is successful and None otherwise."""
		if not fromMgr:
			# Our manager needs to know about this
			# So make sure we go through him
			return self.manager().login(self, password)
		else:
			if password==self.password():
				self._isActive = 1
				self._lastLoginTime = self._lastAccessTime = time.time()
				return self
			else:
				if self._isActive:
					# Woops. We were already logged in, but we tried again
					# and this time it failed. Logout:
					self.logout()
				return None

	def logout(self, fromMgr=0):
		if not fromMgr:
			# Our manager needs to know about this
			# So make sure we go through him
			self.manager().logout(self)
		else:
			self._isActive = 0
			self._lastLogoutTime = time.time()


	## Notifications ##

	def wasAccessed(self):
		self._lastAccessTime = time.time()
