# persistence.py
#
# Copyright 2004,2005 Wichert Akkerman <wichert@wiggy.net>

class SessionObject(object):
	def __init__(self, dbc, table, session, object):
		self._dbc=dbc
		self._table=table
		self._session=session
		self._object=object

		data=dbc.query("SELECT key, value FROM %s WHERE session=%%s AND object=%%s" % self._table,
				(self._session, self._object), "format")
		for (key,value) in data:
			super(SessionObject, self).__setattr__(key, value)
	

	def __setattr__(self, name, value):
		if not name.startswith("_"):
			if hasattr(self, name):
				cmd="UPDATE %s SET value=%%s WHERE session=%%s AND object=%%s AND key=%%s"
			else:
				cmd="INSERT INTO %s (value,session,object,key) VALUES (%%s,%%s,%%s,%%s)"
			self._dbc.execute(cmd % self._table, (value, self._session, self._object, name), "format")

		super(SessionObject, self).__setattr__(name, value)
	

	def __delattr__(self, name):
		super(SessionObject, self).__delattr__(name)
		self._dbc.execute("DELETE FROM %s WHERE session=%%s AND object=%%s AND key=%%s" % self._table,
				(self._session, self._object, name), "format")


class Session:
	def __init__(self, dbc, table, session):
		self.dbc=dbc
		self.table=table
		self.session=session
	

	def keys(self):
		return [x[0] for x in
			self.dbc.query("SELECT DISTINCT object FROM %s WHERE session=%%s" % self.table,
					(self.session,), "format")]
	
	def values(self):
		return [SessionObject(self.dbc, self.table, self.session, x)
				for x in self.keys()]
	

	def __delitem__(self, key):
		if not self.has_key(key):
			raise KeyError, "No sessionobject '%s' known" % key
		self.dbc.execute("DELETE FROM %s WHERE session=%%s AND object=%%s" % self.table,
					(self.session, key), "format")


	def __getitem__(self, key):
		if not self.has_key(key):
			raise KeyError, "No sessionobject '%s' known" % key
		return SessionObject(self.dbc, self.table, self.session, key)


	def __len__(self):
		return int(self.dbc.query("SELECT COUNT(DISTINCT object) FROM %s WHERE session=%%s" % self.table,
					(self.session,), "format")[0][0])

	
	def __contains__(self, key):
		return self.has_key(key)


	def has_key(self, key):
		count=self.dbc.query("SELECT COUNT(DISTINCT object) FROM %s WHERE session=%%s AND object=%%s" % self.table,
					(self.session, key), "format")[0][0]
		return count!=0


	def CreateVariable(self, key):
		return SessionObject(self.dbc, self.table, self.session, key)


class SesDbIterator:
	def __init__(self, db):
		self.cursor=db.dbc.execute("SELECT DISTINCT session FROM %s" % db.table)
	

	def __del__(self):
		self.cursor.close()
	

	def __iter__(self):
		return self


	def next(self):
		res=self.cursor.fetchone()
		if res==None:
			raise StopIteration
		else:
			return res[0].rstrip();


class SessionDb:
	def __init__(self, dbc, table="sessiondata"):
		self.dbc=dbc
		self.table=table


	def keys(self):
		return [x[0] for x in
			self.dbc.query("SELECT DISTINCT session FROM %s" % self.table)]
	

	def values(self):
		return [Session(self.dbc, self.table, x) for x in self.keys()]
	

	def __len__(self):
		return int(self.dbc.query("SELECT COUNT(DISTINCT session) FROM %s" % self.table)[0][0])
	

	def __iter__(self):
		return SesDbIterator(self)


	def __delitem__(self, key):
		if not self.has_key(key):
			raise KeyError, "No session '%s' known" % key
		self.dbc.execute("DELETE FROM %s WHERE session=%%s" % self.table,
				(key,), "format")


	def __getitem__(self, key):
		if not self.has_key(key):
			raise KeyError, "No session '%s' known" % key
		return Session(self.dbc, self.table, key)


	def __contains__(self, key):
		return self.has_key(key)


	def has_key(self, key):
		count=self.dbc.query("SELECT COUNT(DISTINCT session) FROM %s WHERE session=%%s" % self.table,
				(key,), "format")[0][0]
		return count!=0

