import socket, threading, queue
from gi.repository import GObject

def controlServerEntrypoint(f):
	# mark the method as something that requires view's class
	f.is_control_server_entrypoint = True
	return f

class ControlServer():
	def __init__(self, videomix):
		'''Initialize server and start listening.'''
		self.videomix = videomix

		sock = socket.socket()
		sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		sock.bind(('0.0.0.0', 23000))
		sock.listen(1)

		# register socket for callback inside the GTK-Mainloop
		GObject.io_add_watch(sock, GObject.IO_IN, self.listener)

	def listener(self, sock, *args):
		'''Asynchronous connection listener. Starts a handler for each connection.'''
		conn, addr = sock.accept()
		print("Connection from ", addr)

		# register data-received handler inside the GTK-Mainloop
		GObject.io_add_watch(conn, GObject.IO_IN, self.handler)
		return True

	def handler(self, conn, *args):
		'''Asynchronous connection handler. Processes each line from the socket.'''
		line = conn.recv(4096)
		if not len(line):
			print("Connection closed.")
			return False

		r = self.processLine(line.decode('utf-8'))
		if isinstance(r, str):
			conn.send((r+'\n').encode('utf-8'))
			return False

		conn.send('OK\n'.encode('utf-8'))
		return True




	def processLine(self, line):
		command, argstring = (line.strip()+' ').split(' ', 1)
		args = argstring.strip().split()
		print(command, args)

		if not hasattr(self.videomix, command):
			return 'unknown command {}'.format(command)

		f = getattr(self.videomix, command)
		if not hasattr(f, 'is_control_server_entrypoint'):
			return 'method {} not callable from controlserver'.format(command)

		try:
			return f(*args)
		except Exception as e:
			return str(e)