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

from winswitch.ui.config_common import table_init, add_tableline
from winswitch.objects.server_command import ServerCommand
from winswitch.ui.session_start_options import SessionStartOptions, CELL_WIDTH
from winswitch.virt.options_common import SCREEN_SIZE
from winswitch.util.config import get_settings
from winswitch.consts import SSH_TYPE
from winswitch.ui import icons


class SessionStartDialog(SessionStartOptions):
	"""
	This dialog allows the user to start a command on one of the servers we are connected to.
	It extends SessionStartOptions to allow the user to select:
	* the server to use
	* the category of the command
	* the actual command
	Plus all the options from SessionStartOptions
	"""

	def __init__(self, servers, server, client_utils, command_type, callback):
		self.servers = [x for x in servers if x.enabled]
		self.category_commands = None			# list of (category, [commands])
		self.category = None
		self.desktop_mode = command_type==ServerCommand.DESKTOP
		if server is None:
			server = self.get_default_server()
		SessionStartOptions.__init__(self, server, client_utils, None, command_type, None, callback, None, True)
		self.add_update_notification_callbacks()
		self.window.set_geometry_hints(self.window, min_width=520, min_height=420)

	def local_init(self):
		self.assign_command_and_categories()


	def get_default_server(self):
		ID = get_settings().default_server
		our_session_types = get_settings().get_available_session_types(self.desktop_mode, hide_suboptimal=True)
		ignore_types = [SSH_TYPE]
		best = []
		for server in self.servers:
			if ID and server.ID==ID:
				if server.is_connected():
					return	server
				else:
					best.append(server)
			elif server.is_connected():
				server_session_types = server.get_available_session_types(self.desktop_mode, hide_suboptimal=True)
				matches = [x for x in server_session_types if (x in our_session_types and x not in ignore_types)]
				if len(matches):
					best.insert(0, server)
				else:
					best.append(0, server)
		if len(best)==0:
			return	None
		return best[0]

	def assign_command_and_categories(self):
		if not self.server:
			return
		(self.category_commands, _) = self.get_session_types_for_command_type(self.command_type)
		commands = sorted(self.server.get_command_list_for_type(self.command_type))
		if self.command_type==ServerCommand.COMMAND:
			self.category_commands = self.ui_util.group_commands_in_categories(self.server, commands)
		elif self.command_type==ServerCommand.DESKTOP:
			self.category_commands = [(self.ui_util.get_misc_menu(), commands)]
		else:
			self.serror("invalid command type: %s" % self.command_type)
			return
		#select the first category if none are set
		if self.category is None and len(self.category_commands)>0:
			(self.category, _) = self.category_commands[0]

	def get_title(self):
		if self.desktop_mode:
			return "Start Remote Desktop"
		return	"Start Remote Application"

	def create_form_box(self):
		box = gtk.VBox(False, 0)
		box.set_spacing(15)
		#title:
		hbox = gtk.HBox(False, 0)
		if self.command_type==ServerCommand.COMMAND:
			icon = icons.get("run")
		elif self.command_type==ServerCommand.DESKTOP:
			icon = icons.get("desktop")
		else:
			icon = None	#maybe should bail out here?
		if icon:
			hbox.pack_start(self.ui_util.scaled_image(icon, 48))
		vbox = gtk.VBox(False, 0)
		vbox.pack_start(self.ui_util.make_label(self.get_title(), "sans 16"))
		hbox.pack_start(vbox)
		box.pack_start(hbox)
		#form
		table = table_init(self)
		#select server:
		(_, self.server_select) = add_tableline(self, table, "On Server", gtk.OptionMenu(), homogeneous=CELL_WIDTH)
		self.server_select.connect("changed", self.server_changed)
		#categories
		(self.categories_label, self.categories) = add_tableline(self, table, "Category", gtk.OptionMenu(), homogeneous=CELL_WIDTH)
		self.categories.connect("changed", self.category_changed)
		(_, self.commands) = add_tableline(self, table, "Command", gtk.OptionMenu(), homogeneous=CELL_WIDTH)
		#commands
		self.commands.connect("changed", self.command_changed)
		#Adds the form elements from session_start_options.py
		self.add_start_options(table)
		box.pack_start(table)

		box.pack_start(self.create_button_box())
		return	box

	def start_session(self, *args):
		session_type = self.get_selected_session_type()
		if session_type and self.server_command:
			screen_size = self.session_start_options.get(SCREEN_SIZE)
			bookmark = self.can_bookmark and self.bookmark.get_active()
			self.close_window()
			gobject.idle_add(self.callback, self.server, self.server_command, session_type, screen_size, self.session_start_options, bookmark)

	def server_changed(self, *args):
		active = self.server_select.get_history()
		if active>=0 and (not self.server or not self.populating):	#ignore changes we generated ourselves by populating the form (unless no server is set)
			new_server = self.servers[active]
			if new_server==self.server:
				return	#unchanged
			self.server = new_server
			self.sdebug("new server=%s" % self.server, *args)
			self.assign_command_and_categories()
			self.populate_category_commands()
			self.populate_commands()
			old_session_type = self.current_session_type
			self.assign_session_types()
			self.populate_session_types()
			if self.current_session_type!=old_session_type:
				self.show_session_type_options()
		self.check_server()

	def get_server_warning_text(self):
		"""
		Override this method so we can add some extra checks.
		"""
		cat = 0
		if self.category_commands:
			cat = len(self.category_commands)
		if cat==0 or (cat==1 and len(self.get_commands())==0):
			return "This server does not export any commands!"
		return SessionStartOptions.get_server_warning_text(self)

	def command_changed(self, *args):
		if self.populating and self.server_command:
			return		#ignore changes we generated ourselves by populating the form (unless server_command is not set yet)
		commands = self.get_commands()
		index = self.commands.get_history()
		if index<0:
			index = 0
		if index>=0 and index<len(commands):
			self.server_command = commands[index]				#new selected command
		else:
			self.server_command = None

	def category_changed(self, *args):
		index = self.categories.get_history()
		if self.populating and self.category:
			return
		if index<0:
			index = 0
		new_category = None
		if index>=0 and index<len(self.category_commands):
			(new_category, _) = self.category_commands[index]	#new selected category
		if new_category==self.category:
			return
		self.category = new_category
		self.populate_commands()

	def get_commands(self):
		if not self.category:
			return	[]
		#find the commands for this category - not using a dict() as it does not preserve ordering.
		for cat,commands in self.category_commands:
			if cat==self.category:
				return	commands
		return	[]


	def populate_servers(self):
		"""
		Populate the self.server_select list of servers.
		"""
		self.sdebug()
		servers_menu = gtk.Menu()
		selected_index = -1
		index = 0
		for s in self.servers:
			icon = self.ui_util.get_server_type_icon(s.type)
			item = self.ui_util.menuitem(s.get_display_name(), icon, None)
			item.set_sensitive(s.is_connected())
			servers_menu.append(item)
			if self.server==s:
				selected_index = index
			index += 1
		self.server_select.set_menu(servers_menu)
		if selected_index>0:
			self.server_select.set_history(selected_index)
		self.server_select.show_all()
		self.server_select.set_sensitive(len(self.servers)>0)


	def populate_commands(self):
		"""
		Populate the self.commands list of commands for the selected category.
		"""
		self.sdebug()
		commands_menu = gtk.Menu()
		selected_index = -1
		index = 0
		commands = self.get_commands()
		for command in commands:
			commands_menu.append(self.ui_util.get_command_menu_entry(self.server, command))
			if command == self.server_command:
				selected_index = index
			index += 1
		self.commands.set_menu(commands_menu)
		if selected_index>=0:
			self.commands.set_history(selected_index)
		self.commands.show_all()
		self.start_button.set_sensitive(len(commands)>0)

	def populate_category_commands(self):
		if len(self.category_commands)==0:
			self.category = None
			self.categories.hide()
			self.categories_label.hide()
		elif len(self.category_commands)==1:
			(self.category,_) = self.category_commands[0]
			self.categories.hide()
			self.categories_label.hide()
		else:
			categories_menu = gtk.Menu()
			selected_index = -1
			index = 0
			for category,_ in self.category_commands:
				categories_menu.append(self.ui_util.get_command_menu_entry(self.server, category))
				if category == self.category:
					selected_index = index
				index += 1
			self.categories.set_menu(categories_menu)
			if selected_index>=0:
				self.categories.set_history(selected_index)
			self.categories.show_all()
			self.categories_label.show()

	def do_populate_form(self):
		self.populate_servers()
		self.assign_command_and_categories()
		self.populate_category_commands()
		self.populate_commands()
		SessionStartOptions.do_populate_form(self)		#populates session types, their options, bookmark
