#!/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 sys
import thread

from winswitch.util.process_util import exec_nopipe
from winswitch.consts import X_PORT_BASE
from winswitch.objects.global_settings import get_settings
from winswitch.util.simple_logger import Logger
from winswitch.net.net_util import get_port_mapper
from winswitch.util.main_loop import callFromThread

xming_util = None
def get_xming_util():
	global xming_util
	if not xming_util and sys.platform.startswith("win"):
		xming_util = Xming_Util()
	return	xming_util

class	Xming_Util:
	def	__init__(self):
		Logger(self, log_colour=Logger.CYAN)
		self.shared_display = None
		self.shared_process = None
		self.display_cache = {}

	def close(self):
		"""
		Close all the Xming displays.
		(there may be just one if shared_xming_display=True)
		This method may be called multiple times (ie: when multiple client classes use it)
		"""
		self.slog("displays=%s" % self.display_cache)
		for display,process in self.display_cache.items():
			self.sdebug("stopping process %s for display %s" % (process, display))
			process.stop()
		self.display_cache = {}

	def	get_Xming_display(self, ready_cb, err_cb):
		""" """
		if get_settings().shared_xming_display:
			if self.shared_display and self.shared_process:
				#shared display exists, verify it is still alive:
				if self.shared_process and self.shared_process.poll() is None:
					#shared display exists and is still alive, use it:
					ready_cb(self.shared_display, self.shared_process)
					return
				self.shared_display = None
				self.shared_process = None
			def assign_shared(display, process):
				self.shared_display = display
				self.shared_process = process
				ready_cb(display, process)
			self.start_Xming_display(assign_shared, err_cb)	#start the shared display
			return
		#not sharing, so just start a new one:
		#this is slow so use a thread (safe since we only use callbacks via callFromThread)
		thread.start_new_thread(self.start_Xming_display, (ready_cb, err_cb))

	def start_Xming_display(self, ready_cb, err_cb):
		display_no = get_port_mapper().get_free_port(X_PORT_BASE)
		cmd = [get_settings().xming_command, ":%d" % display_no, "-ac", "-multiwindow", "-clipboard", "-notrayicon"]
		display = "127.0.0.1:%d" % display_no
		self.sdebug("display=%s, cmd=%s, display=%s" % (display, cmd, display))
		xming_process = exec_nopipe(cmd)
		if not xming_process or xming_process.poll():
			self.debug("() xming process failed... %s" % xming_process)
			callFromThread(err_cb, "coult not start Xming process")
		else:
			self.sdebug("xming process pid=%s" % xming_process.pid)
			self.display_cache[display] = xming_process
			callFromThread(ready_cb, display, xming_process)
