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

from winswitch.objects.common import ModifiedCallbackObject
from winswitch.objects.session import Session

""" This is the client representation of the sessions it manages """
class ClientSession(Session):

	SESSION_UPDATE_FIELDS = Session.SESSION_UPDATE_COMMON_FIELDS[:]
	PERSIST = Session.PERSIST_COMMON

	def __init__(self):
		Session.__init__(self)

	def __str__(self):
		return	"ClientSession(%s - %s - %s)" % (self.display, self.session_type, self.status)

	def init_transients(self):
		Session.init_transients(self)
		self.tunnels = []				# the actual tunnel objects
		self.client_pid = -1			# xpra client/nxproxy client pid

		self.pre_connected = False		# for some sessions, we connect in advance - even if the session has self.preload=True
		self.port_tested = False		# have we checked connectivity?

		#used client-side to keep track of all the processes belonging to that session, ie: vnc client, Xming, ...
		self.processes = []
		self.window_names = []

		self.local_display = os.getenv("DISPLAY", ":0")
		self.local_display_process = None	#used on win32 when starting Xming

		self.kill_client = False					#record when we attempt to kill the client ourselves and dont report this as an error
		self.client_start_time = None

		#the gst pipelines running on the client (processes):
		self.local_sound_pipeline = {}				#for each of True|False: {True:subprocess, False:subprocess}
		self.local_sound_is_monitor = {}

		self.env = os.environ.copy()

	def close(self):
		Session.close(self)

	def is_local_display(self, our_uuid, local_server=False):
		from winswitch.consts import X11_TYPE, WINDOWS_TYPE, OSX_TYPE
		if self.session_type not in [X11_TYPE, WINDOWS_TYPE, OSX_TYPE]:
			return	False
		#is our own display (direct match):
		if self.owner==our_uuid:
			return	True
		#these session types are unique per server, so a local server is enough to tell us this is a local display:
		if local_server and self.session_type in [WINDOWS_TYPE, OSX_TYPE]:
			return	True
		return	False

	def update(self, from_obj):
		#these should never change during the session's lifetime:
		assert self.display == from_obj.display
		assert self.session_type == from_obj.session_type
		assert self.requires_tunnel == self.requires_tunnel
		#password and icons are only set (via dedicated commands), never updated

		self.timed_out = False
		ModifiedCallbackObject.update_fields(self, ClientSession.SESSION_UPDATE_FIELDS, from_obj, False, False)
		self.set_status(from_obj.status, False)
		self.touch()

	def is_sound_live(self, in_or_out, monitor_flag=None):
		pipeline = self.local_sound_pipeline.get(in_or_out)
		if not pipeline:
			return	False
		if monitor_flag is not None:
			#ensure the flag also matches since specified:
			monitor = self.local_sound_is_monitor.get(in_or_out)
			assert monitor is not None
			if monitor!=monitor_flag:
				return	False
		return	pipeline.poll() is None

	def stop_sound(self, in_or_out, monitor_flag=None):
		assert in_or_out is not None
		if not self.is_sound_live(in_or_out, monitor_flag):
			self.slog("pipeline already stopped / never started", in_or_out, monitor_flag)
			return

		from winswitch.util.process_util import subprocess_terminate
		pipeline = self.local_sound_pipeline.get(in_or_out)
		self.slog("stopping %s" % pipeline, in_or_out, monitor_flag)
		subprocess_terminate(pipeline)
		self.local_sound_pipeline[in_or_out] = None
		self.local_sound_is_monitor[in_or_out] = None
		self.touch()
