#!/usr/bin/env python

# This file is part of Window-Switch.
# Copyright (c) 2009-2013 Antoine Martin <antoine@nagafix.co.uk>
# Window-Switch is released under the terms of the GNU GPL v3

import twisted.internet
reactor = twisted.internet.reactor
from twisted.protocols import basic

# Our imports
from winswitch.util.file_io import get_local_client_socket_path
from winswitch.util.simple_logger import Logger
from winswitch.util.common import visible_command
from winswitch.net.local_common import RESPONSE_BUSY
from winswitch.consts import DELIMITER


class LocalSocketListener:
	def __init__(self, line_handler_factory):
		Logger(self, log_colour=Logger.YELLOW)
		self.line_handler_factory = line_handler_factory
		self.terminated = False
		self.listening_port = None
		self.socket_filename = get_local_client_socket_path()

	def stop(self):
		self.log()
		self.terminated = True
		if self.listening_port:
			self.listening_port.stopListening()

	def start(self):
		factory = LocalSocketListenerFactory(self)
		self.listening_port = reactor.listenUNIX(self.socket_filename, factory, )
		self.slog("listening on %s" % self.socket_filename)


class LocalSocketListenerChannel(basic.LineReceiver):
	def __init__ (self):
		Logger(self)
		self.debug()
		self.handler = None

	def __str__(self):
		return	"LocalSocketListenerChannel"

	def disconnect(self):
		self.debug()
		self.transport.loseConnection()

	def connectionMade(self):
		self.log()
		self.factory.numProtocols = self.factory.numProtocols+1
		if self.factory.numProtocols > 100:
			self.transport.write(RESPONSE_BUSY)
			self.transport.loseConnection()
			return
		self.delimiter = DELIMITER
		self.handler = self.factory.listener.line_handler_factory(self.sendLine)

	def connectionLost(self, reason):
		self.slog(None, reason)
		self.factory.numProtocols = self.factory.numProtocols-1

	def lineReceived(self, line):
		self.sdebug(None, visible_command(line))
		self.handler.handle(line)


class LocalSocketListenerFactory(twisted.internet.protocol.ClientFactory):
	# the class of the protocol to build when new connection is made
	protocol = LocalSocketListenerChannel

	def __init__ (self, listener):
		Logger(self)
		self.listener = listener
		self.numProtocols = 0
		self.sdebug(None, listener)

	def __str__(self):
		return	"LocalSocketListenerFactory(%s)" % self.listener

	def clientConnectionLost(self, connector, reason):
		self.serror(None, connector, reason)

	def clientConnectionFailed(self, connector, reason):
		self.serror(None, connector, reason)
