#!/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

from winswitch.net.conch_channels import ExecLineChannel
from winswitch.consts import LOCALHOST
from winswitch.util.common import visible_command
from winswitch.util.simple_logger import Logger
from winswitch.net.net_util import get_port_mapper
from conch_test_common import make_factory
from winswitch.util.main_loop import test_loop, callLater, connectTCP
logger = Logger("conch_watch_test")

from twisted.internet.protocol import ClientFactory
from twisted.protocols import basic

channel = None
command_tunnel = None

class ServerConnection(basic.LineReceiver):

	def __init__(self):
		Logger(self)
		self.MAX_LENGTH = 1024*64

	def __str__(self):
		return	"ServerConnection"

	def connectionMade(self):
		self.delimiter = "\n"
		self.write("sync")
		self.slog()

	def connectionLost(self, reason):
		self.slog()

	def write(self, data):
		self.sendLine(data)

	def lineReceived(self, line):
		self.slog(None, visible_command(line))


class ServerConnectionFactory(ClientFactory):
	protocol = ServerConnection

	def __init__ (self, host, port):
		Logger(self)
		self.sdebug(None, host,port)
		self.host = host
		self.port = port

	def __str__(self):
		return	"ServerConnectionFactory(%s,%s)" % (self.host, self.port)

	def clientConnectionLost(self, connector, reason):
		self.slog(None, connector, reason)
		self.retry(connector)
	
	def retry(self, connector):
		callLater(2, connector.connect)

	def clientConnectionFailed(self, connector, reason):
		self.retry(connector)

def test_connect(local_port):
	client_factory = ServerConnectionFactory(LOCALHOST, local_port)
	connectTCP(LOCALHOST, local_port, client_factory, timeout=20)

def handle_server_line(s):
	global channel
	global command_tunnel
	logger.slog(None, s)
	#0.0.0.0:40557 119779272758314
	if command_tunnel is not None:
		return
	if len(s)<20:
		return
	hostip_id = s.split(" ")
	if len(hostip_id)!=2:
		return
	host_ip = hostip_id[0].split(":")
	if len(host_ip)!=2:
		return
	remote_host = LOCALHOST
	remote_port = int(host_ip[1])
	local_port = get_port_mapper().get_free_command_port()
	command_tunnel = channel.connection.forward_port(local_port, remote_host, remote_port)
	test_connect(local_port)

def make_channel(command, connection):
	global channel
	channel = ExecLineChannel(command, None, handle_server_line, connection)

def ssh_watch(host, port, command):
	factory = make_factory(host, port)
	factory.channel_constructors.append(lambda connection : make_channel(command, connection))
	connectTCP(host, port, factory)

def test_server_portinfo_monitor_localhost():
	ssh_watch(LOCALHOST, 22, "winswitch_server_portinfo_monitor")

def main():
	test_loop(test_server_portinfo_monitor_localhost)


if __name__ == "__main__":
	main()
