import sys,re,math,os,string,random,time
from datetime import datetime
from twisted.web import resource, server

from twisted.internet import reactor,task

try:
	# old twisted
	from twisted.web import http
except:
	# new twisted
	from twisted.protocols import http

from twisted.python import threadable

# spawned per request
class LazyWebRequest(resource.Resource):
	
	isLeaf = 1
	
	def __init__(self, controller, state):
		self.controller = controller
		self.state = state

	def render_GET(self, request):
		
		self.controller.addChannel(self, request)

		self.boundary = string.join(random.sample(string.letters, 42),'')

		# replace content magic 
		request.setHeader("Content-Type", "multipart/x-mixed-replace;boundary=%s" % self.boundary);
	
		# tell me when the connection dies 
		request.notifyFinish().addBoth(self.lostIt, request)

		self.syncstate(request)
		
		return server.NOT_DONE_YET
	
	def lostIt(self, reason, request):
		self.controller.removeChannel(self, request)

	def syncstate(self, request):
		snapshot = self.state.snapshot()
		self.writechunk(request, snapshot)
		
	def writechunk(self, request, msg):
		type = self.state.type
		request.write("--%s\n" % self.boundary)
		request.write("Content-Type: %s\n\n" % type)
		request.write(msg)
		request.write("\n")
	
	def render_REPLACE(self, request, message):
		self.writechunk(request, message)

class LazyWebChannel(resource.Resource):
	
	def __init__(self, controller, state):
		self.controller = controller
		self.state = state
		self.children = {}

	def getChild(self, path, request):
		return LazyWebRequest(self.controller, self.state)

class LazyWebController(object):
	synchronized = ["addChannel", "removeChannel", "update"]
	def __init__(self):
		self.channels = []
	
	def addChannel(self, chan, r):
		print "adding %s:%d" % (r.client.host, r.client.port)
		self.channels.append((chan, r))
	
	def removeChannel(self, chan, r):
		print "removing %s:%d" % (r.client.host, r.client.port)
		try:
			self.channels.remove((chan,r))
		except:
			pass

	def update(self, m):
		for (c,r) in self.channels:
			# update all
			c.render_REPLACE(r, m)

# gotta lurrrve twisted
threadable.synchronize(LazyWebController)


# triggers
class TimeNowTrigger(object):
	type = "text/plain"
	def __init__(self, cb):
		self.cb = cb
	
	def check(self):
		self.cb(self.snapshot())
	
	def snapshot(self):
		return datetime.now().strftime("%A %d. %B %Y  %H:%M:%S")

if __name__ == '__main__':
	controller = LazyWebController()
	trigger = TimeNowTrigger(controller.update)

	#from svgclock import SvgClockTrigger
	#trigger = SvgClockTrigger(controller.update)

	site = server.Site(LazyWebChannel(controller, trigger))
	
	reactor.listenTCP(4081, site)

	updater = task.LoopingCall(trigger.check)
	updater.start(1)
	
	print "ok, running on 4081"
	reactor.run()
