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

from winswitch.virt.gstvideo_client_base import GSTVideoClientBase
from winswitch.virt.client_options_base import ClientOptionsBase
from winswitch.virt.client_util_base import ClientUtilBase
from winswitch.virt.options_common import FRAMERATE, GST_VIDEOSCALE_METHOD, GST_VIDEO_CODEC
from winswitch.util.common import parse_screensize

FRAMERATES = [1,5,10,15,20,25,30,50]
MIN_SCALED_WIDTH = 64
MIN_SCALED_HEIGHT = 48

CODEC_NONE = "None"

class	GSTVideoClientUtil(GSTVideoClientBase, ClientOptionsBase):
	""" Extends GSTVideoClientBase to add widget options for selecting framerate and videoscale """

	def	__init__(self, update_session_status, notify_callback):
		GSTVideoClientBase.__init__(self, update_session_status, notify_callback)


	def get_default_desktop_size(self, server_command, command_type, shadowed_session):
		""" override so we find the closest match since get_desktop_sizes() returns a list that is very likely to be different from the global options """
		v = ClientUtilBase.get_default_desktop_size(self, server_command, command_type, shadowed_session)
		self.sdebug("default desktop size=%s" % str(v), server_command, command_type, shadowed_session)
		if not v:
			return	None
		sizes = self.get_desktop_sizes(server_command, command_type, shadowed_session)
		self.sdebug("sizes=%s" % str(sizes), server_command, command_type, shadowed_session)
		if not sizes:
			return	None
		vx,vy = v
		for x,y in sizes:
			if x<=vx and y<=vy:
				self.sdebug("%sx%s" % (x,y), server_command, command_type, shadowed_session)
				return	(x,y)
		return	None

	def get_desktop_sizes(self, server_command, command_type, shadowed_session):
		""" override so we can generate the list, as the sizes must be proportional to the existing session's screen size """
		self.sdebug(None, server_command, command_type, shadowed_session)
		if shadowed_session:
			parsed = parse_screensize(shadowed_session.screen_size)
			if parsed:
				#[(160, 120), (320, 240), (480, 360), (640, 480), (800, 600), (1024, 768), (1280,1024), (1440,900), (1600, 1200), (1920,1080), (2560,1600)]
				w,h,_ = parsed
				sizes = []
				sizes.append((w,h))
				while w>MIN_SCALED_WIDTH and h>MIN_SCALED_HEIGHT:
					scaled = None
					for d in [1.5,2,3,5]:
						""" the pipeline we define doesn't do any aspect ratio scaling, so we must ensure integer divisions don't have remainders: """
						if int(w/d)==(float(w)/d) and int(h/d)==(float(h)/d):
							w = int(w/d)
							h = int(h/d)
							scaled = (w,h)
							break
					if scaled:
						sizes.append(scaled)
					else:
						break
				self.sdebug("=%s" % sizes, server_command, command_type, shadowed_session)
				return	sizes
		return	self.desktop_sizes

	def get_video_compression_widget(self, server, current_options, change_cb):
		""" Select which video encoder to use for compression """
		cb = gtk.combo_box_new_text()
		#find the current value:
		current_codec = None
		if current_options and GST_VIDEO_CODEC in current_options:
			try:
				current_codec = current_options[GST_VIDEO_CODEC]
			except:
				pass
		self.slog("server.gstvideo_codecs=%s, settings.gstvideo_codecs=%s" % (server.gstvideo_codecs, self.settings.gstvideo_codecs))
		codecs = self.get_valid_video_codecs(server)
		if len(codecs)==0:
			return	None
		#populate drop down:
		index = 1
		active = 1
		codecs.insert(0, CODEC_NONE)
		for codec in codecs:
			cb.append_text("%s" % codec)
			if current_codec is not None and current_codec==codec:
				active = index
			index += 1
		if active<=len(codecs):
			cb.set_active(active)
		self.setup_combo_callback(cb, GST_VIDEO_CODEC, change_cb)
		return cb

	def get_framerate_widget(self, server, current_options, change_cb):
		""" A combo box where users can select jpeg compression	"""
		cb = gtk.combo_box_new_text()
		#find the current value:
		current_framerate_value = 5
		if current_options and FRAMERATE in current_options:
			try:
				current_framerate_value = int(current_options[FRAMERATE])
			except:
				pass
		#populate drop down:
		index = 0
		active = 0
		for fr in FRAMERATES:
			cb.append_text("%s" % fr)
			if current_framerate_value==fr:
				active = index
			index += 1
		if active>=0:
			cb.set_active(active)
		self.setup_combo_callback(cb, FRAMERATE, change_cb, cast_to_int=True)
		return cb

	def get_videoscale_method_widget(self, server, current_options, change_cb):
		""" A combo box where users can select videoscale method """
		cb = gtk.combo_box_new_text()
		#find the current value:
		current_scalemethod_value = 1
		if current_options and GST_VIDEOSCALE_METHOD in current_options:
			try:
				current_scalemethod_value = int(current_options[GST_VIDEOSCALE_METHOD])
			except:
				pass
		cb.append_text("fast and ugly")
		cb.append_text("slower but prettier")
		cb.append_text("slow")
		if current_scalemethod_value>=0 and current_scalemethod_value<3:
			cb.set_active(current_scalemethod_value)
		self.setup_combo_callback(cb, GST_VIDEOSCALE_METHOD, change_cb, cast_to_int=True, default=1)
		return cb

	def get_options_widgets(self, server, server_command, shadowed_session=None, current_options=None, default_options=None, change_cb=False):
		""" GST options: framerate """
		options = self.get_options(current_options, default_options)
		widgets = []
		if default_options is not None:	#not in edit mode
			compression = self.get_video_compression_widget(server, options, change_cb)
			if compression:		#may not be shown if no options are available
				widgets.append(("Video Compression", compression))
			widgets.append(("Framerate", self.get_framerate_widget(server, options, change_cb)))
			widgets.append(("Scaling Method", self.get_videoscale_method_widget(server, options, change_cb)))
			self.add_screen_size_widget(widgets, server, server_command, shadowed_session, options, change_cb)
		return	widgets
