#!/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 os
import re

from winswitch.consts import NX_TYPE, APPLICATION_NAME
from winswitch.globals import USERNAME, WIN32, OSX
from winswitch.util.common import get_bool
from winswitch.virt.client_util_base import ClientUtilBase
from winswitch.virt.nx_common import nx_display_value, SET_COOKIE
from winswitch.util.file_io import get_client_session_dir
from winswitch.virt.options_common import CLIPBOARD, FULLSCREEN


class	NXClientBase(ClientUtilBase):
	"""
	Utility class used by the client to attach to an NX session.
	(not to be confused with the NX client/server terminology which is reversed)
	"""
	DEFAULT_NXPROXY_OPTIONS = {
					"cleanup": 0,
					"product": APPLICATION_NAME.replace(" ", ""),
					"media": 0
					}
	CONNECTED_RE = re.compile(r"Info:\s*Established X server connection.")
	GENERIC_ERROR = re.compile(r"Warning:\sCouldn't start '/usr/NX/bin/nxclient'.")


	def	__init__(self, update_session_status, notify_callback):
		ClientUtilBase.__init__(self, NX_TYPE, update_session_status, notify_callback)
		self.client_log_actions[NXClientBase.CONNECTED_RE] 			= self.handle_line_log
		self.client_log_actions[NXClientBase.GENERIC_ERROR]			= self.client_connect_error		#this is not a connection error (stricly speaking) - but worth a check


	def get_session_pids(self, session):
		pids = self.get_client_pids(session)
		if WIN32:
			#on win32, we have to look for the Xming pid
			if session.local_display_process:
				# and session.local_display_process.poll():??
				pids.append(session.local_display_process.pid)
		return	pids





	def do_real_attach(self, server, session, host, port):
		self.sdebug(None, server, session, host, port)
		env = None	#will use default
		# On win32 we must start a display
		if WIN32 and (not session.local_display or not session.local_display_process):
			def Xming_ready():
				env = os.environ.copy()
				env["DISPLAY"] = session.local_display
				if "HOME" not in env:
					if "HOMEDRIVE" in env and "HOMEPATH" in env:
						env["HOME"] = "%s%s" % (env["HOMEDRIVE"], env["HOMEPATH"])
					else:
						self.notify_error("Failed to start session",
							"Cannot find the home directory!")
						return
				self.start_nxproxy(server, session, host, port, env)
			self.win32_Xming_session_start(session, Xming_ready)
			return

		# on OSX we may not have an xmodmap yet:
		has_xmodmap_data = bool(self.settings.xmodmap_keys) or bool(self.settings.xmodmap_modifiers)
		if OSX and not has_xmodmap_data:
			self.slog("no xmodmap data, populating it and sending it to all the servers, including %s" % server.link, server, session, host, port)
			#this will take care of updating all the servers:
			self.settings.populate_xmodmap()
		elif has_xmodmap_data and server.link and server.link.client:
			try:
				server.link.client.may_send_xmodmap()
			except Exception, e:
				self.serr(None, e, server, session, host, port)
		self.start_nxproxy(server, session, host, port, env)

	def start_nxproxy(self, server, session, host, port, env):
		# prepare the command line and options
		nxproxy_command = self.settings.nxproxy_command
		nx_options = self.get_nxproxy_options(session, host, port, server.line_speed)
		nx_display  = nx_display_value(nx_options, USERNAME, session.display, agent=False, optionsfile_dir=get_client_session_dir(session.ID))
		cmd = [nxproxy_command, "-S", nx_display]
		self.exec_client(server, session, cmd, env=env)

	def get_nxproxy_options(self, session, host, port, line_speed):
		nx_options = self.DEFAULT_NXPROXY_OPTIONS.copy()
		clipboard = session.options.get(CLIPBOARD)
		if clipboard is not None and not get_bool(clipboard):
			nx_options["clipboard"] = "0"
		fullscreen = session.options.get(FULLSCREEN)
		if fullscreen is not None and get_bool(fullscreen):
			nx_options["fullscreen"] = "1"
		nx_options["connect"] = "%s" % (host)
		nx_options["port"] = "%d" % (port)
		if session.password and SET_COOKIE:
			nx_options["cookie"] = session.password
		#keyboard undocumented NX magic:
		rules = "evdev"
		if self.settings.xkbmap_layout:
			#trim extra layouts, ie: fr_CH,us -> fr
			layout = self.settings.xkbmap_layout.split(",")[0].split("_")[0]
		else:
			layout = "us"
		if WIN32:
			rules = "pc105"
		nx_options["keyboard"] = "%s/%s" % (rules, layout)
		self.slog("=%s" % nx_options, session, host, port, line_speed)
		return	nx_options

	def get_options_defaults(self):
		return	{
				CLIPBOARD: True,
				FULLSCREEN: False,
				}
