import ldap
import time 
import Cippie
import traceback
import sys

class ChangeManager:

	def __init__(self):
		self.cm = Cippie.Cippie()
		self.err = self.cm.showErrors()
		self.c = self.cm.getConnection()
		if self.cm.hasError(): 
			self.err.append (self.cm.showErrors())
			print(self.cm.showErrors ())

	def getChildren (self, dn, attrs):
		try:
			return self.c.search_s(dn, ldap.SCOPE_ONELEVEL,"objectclass=*")
		except ldap.LDAPError,e:
			self.handleLDAPException (e, "")
			return []
	
	def getAttrs (self, dn, attrs):
		try:
			res = self.c.search_s (dn, ldap.SCOPE_BASE,"objectclass=*",attrs)				
			return res[0][1]	
			#l = {}
			#for a in attrs:
			#	if res[0][1].has_key(a):
			#		l[a]=res[0][1][a]
			#return l			
		except ldap.LDAPError,e:
			self.handleLDAPException (e, "")
			return {}
		
	def getCourseList (self,term):
		return self.getChildren (self.cm.getCourseContext(term),["cn","description","l"])
				
	def getCourseDetails (self,term, course):	
		return self.getAttrs (self.courseDN(term, course),["cn", "description", "l"])

	def getCourseStudents (self,term, course,teststud=0):
		l = self.getAttrs (self.courseDN(term, course), ['uniqueMember'])
		if l.has_key('uniqueMember'):
			if teststud == 1: #return list as is
				return l['uniqueMember']
			else: #purge teststud from list, default
				try:
					l['uniqueMember'].remove('cn=teststud,ou=Studenten,ou=Vetmed,o=uni-muenchen')
				except ValueError:
					pass
				return l['uniqueMember']
		else:
			return []
	
	def isRegistered (self,term, subject, observer):
		l =self.getCourseStudents (term, subject, 1)
		newobserver = "cn=" + observer + ",ou=Studenten,ou=Vetmed,o=uni-muenchen"
		newobserver=newobserver.upper()
		for s in l:
			print s.upper()
			if s != None and newobserver == s.upper():
				return 1
		return 0								
	
	def isOpen (self, term,  subject):
		#return 1 #KLUDGE: outcomment for allowing registration*/
		act = len (self.getCourseStudents (term, subject))
		l = self.getAttrs (self.courseDN(term, subject), ["l"])
		cap = int (str(l["l"][0]))
		if cap > act:
			return 1
		else: 
			return 0
		
	def mark (self, action, term, subject, observer):
		dt = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
		print ("MARK:" + dt + " " + action + " " + term + "/" + subject + " " + observer)
	
	def register (self, term, subject, observer):
		try:
			self.c.modify_s (self.courseDN (term, subject), [(ldap.MOD_ADD, "member", self.studentDN (observer))])
			self.mark ("register success", term, subject, observer) 
		 	return 1
		except ldap.LDAPError,e:
			self.mark ("register failure", term, subject, observer) 
			self.handleLDAPException (e, "")
			return 0

	def addCourse (self, name, longname, description, maxno, term):
		try:
			attrSet = [('objectClass', ["groupOfNames", "top"])]
			attrSet.append(('cn', [name, longname]))	
			attrSet.append(('description', description))
			attrSet.append(('l', maxno))
			attrSet.append(('ou', term))
			attrSet.append(('ACL', '2#entry#[Root]#uniqueMember'))
			#attrSet = ['objectClass': ["groupOfNames", "top"], 'cn': ["cn: " + name, "cn: " + longname], 'description': description, 'l':maxno, 'ou':term, 'ACL':"2#entry#[Root]#uniqueMember"]
			print ("Adding " + self.courseDN (term, name))
			self.c.add_s (self.courseDN (term, name),attrSet)
		except ldap.LDAPError,e:
			self.handleLDAPException (e, "")

	def delCourse (self,name,term):
		try:
			self.c.delete_s(self.courseDN(term,name))
		except ldap.LDAPError,e:
			self.handleLDAPException (e, "")	

	def unregister (self, term, subject, observer):
		try:	
			self.c.modify_s (self.courseDN (term, subject), [(ldap.MOD_DELETE, "member", self.studentDN (observer))])
			self.mark ("unregister success", term, subject, observer) 
			return 1
		except ldap.LDAPError,e:
			self.mark ("unregister failure", term, subject, observer) 
			self.handleLDAPException (e, "")
			return 0

	def checkPassword (self, observer, password):
		try:
			return self.c.compare_s (self.studentDN(observer), "userPassword", password)
		except ldap.LDAPError,e:
			self.handleLDAPException (e, "Invalid credentials: ")
			return 0

	def disconnect (self):
		try:
			self.c.unbind_s()
		except ldap.LDAPError,e:
			self.handleLDAPException (e, "")
	
	def studentDN (self,student):
		return "cn=" + student + ", " + self.cm.getStudentContext()
		
	def courseDN (self,term, subject):
		return "cn=" + subject + ", "  + self.cm.getCourseContext(term)
	
	def getURL (self):
		return "index.html"

	def getMethod (self):
		return "post"
	
	def handleLDAPException (self, e,  comment):
		print "EXCEPTION:START"
		sc = ("%s" % comment)
		se = ("%s" % str(e))
		self.err=self.err + sc
		self.err=self.err + se
		print "%s" % comment
		print str(e)
		print traceback.extract_stack()
		#traceback.print_tb(tb,64,sys.stdout)	
		#traceback.extract_stack()
		print "EXCEPTION:END"
	
	def showErrors (self):
		return ("<blockquote>" + self.err + " Fehler! Bitte senden Sie eine "
			+ " Email an webmaster@vetmed.uni-muenchen.de. Es waere gut wenn Sie "
			+ " den gesamten in Ihrem Browser angezeigten Text hineinpasten. Danke!"
			+ "</blockquote>")
