// AppIndicator.cs created with MonoDevelop
// User: klose at 13:00 20.06.2011
// CVS release: $Id: TrayIcon.cs,v 1.1 2011-06-24 13:55:34 klose Exp $
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2009-2011  Thomas Klose, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;
using Gtk;

using Hiperscan.Unix;


namespace Hiperscan.GUI
{
	
	public class TrayIcon
	{
		private enum TrayIconType
		{
			AppIndicator,
			StatusIcon
		}
		
		private static object icon;
		private static TrayIconType icon_type;
		private static Label indicator_status_label;
		private static CheckMenuItem indicator_visible_item;
		
		public static void Initialize()
		{
			if (TrayIcon.IsInitialized)
			{
				TrayIcon.Visible = true;
				return;
			}

			try
			{
				// AppIndicator is the new default indicator system for Unity
				InitializeAppIndicator();
				TrayIcon.icon_type = TrayIcon.TrayIconType.AppIndicator;
			}
			catch (Exception)
			{
				// fall back to Gtk.StatusIcon
				InitializeStatusIcon();
				TrayIcon.icon_type = TrayIcon.TrayIconType.StatusIcon;
			}
		}
		
		public static void SetTooltip(int shared, int connected)
		{
			if (!TrayIcon.IsInitialized)
				return;
				
			TrayIcon.Tooltip = string.Format(Catalog.GetString("Remote access:\n{0} shared\n{1} connected"),
			                                 shared, connected);
		}

		private static void InitializeAppIndicator()
		{
			AppIndicator.ApplicationIndicator indicator = new AppIndicator.ApplicationIndicator("hiperscan.quickstep", 
			                                                                                    "quickstep", 
			                                                                                    AppIndicator.Category.ApplicationStatus);
			TrayIcon.icon = indicator;
			indicator.Status = AppIndicator.Status.Attention;
			indicator.Menu = TrayIcon.CreateMenu(TrayIconType.AppIndicator);
			TrayIcon.SetTooltip(0, 0);
		}
		
		private static void InitializeStatusIcon()
		{
			StatusIcon status_icon = new StatusIcon();
			TrayIcon.icon = status_icon;
			status_icon.Stock = "hiperscan.quickstep";
			TrayIcon.SetTooltip(0, 0);
			
			status_icon.PopupMenu += delegate(object o, PopupMenuArgs args) {
				Menu menu = TrayIcon.CreateMenu(TrayIconType.StatusIcon);
				
				if (MainClass.OS == MainClass.OSType.Linux)
					status_icon.PresentMenu(menu, (uint)args.Args[0], (uint)args.Args[1]);
				else
					menu.Popup();
			};
			
			status_icon.Activate += delegate(object sender, EventArgs e) {
				if (MainClass.MainWindow.Visible)
					MainClass.MainWindow.Hide();
				else
					MainClass.MainWindow.ShowAll();
			};
			
			status_icon.Visible = true;
		}
		
		public static void Update()
		{
			if (TrayIcon.indicator_visible_item != null)
				TrayIcon.indicator_visible_item.Active = MainClass.MainWindow.Visible;
		}
		
		private static Menu CreateMenu(TrayIconType type)
		{
			Menu menu = new Menu();
		
			MenuItem item;
			
			if (type == TrayIcon.TrayIconType.AppIndicator)
			{
				TrayIcon.indicator_status_label = new Label();
				item = new MenuItem();
				item.Add(TrayIcon.indicator_status_label);
				menu.Append(item);
				
				TrayIcon.indicator_visible_item = new CheckMenuItem(Catalog.GetString("_Show QuickStep"));
				TrayIcon.indicator_visible_item.Active = MainClass.MainWindow.Visible;
				TrayIcon.indicator_visible_item.Toggled += delegate(object sender, EventArgs e) {
					CheckMenuItem cmi = sender as CheckMenuItem;
					if (cmi.Active)
						MainClass.MainWindow.ShowAll();
					else
						MainClass.MainWindow.Hide();
				};
				menu.Append(TrayIcon.indicator_visible_item);
				menu.Append(new SeparatorMenuItem());
			}
			
			item = new ImageMenuItem(Stock.About, MainWindow.UI.AccelGroup);
			item.Activated += MainWindow.UI.OnAboutButtonClicked;
			menu.Append(item);
			
			item = new MenuItem(Catalog.GetString("_Remove from system tray"));
			item.Activated += delegate { 
				if (!MainClass.MainWindow.Visible)
				{
					MessageDialog dialog = new MessageDialog(null, DialogFlags.Modal,
					                                         MessageType.Warning,
					                                         ButtonsType.OkCancel,
					                                         Catalog.GetString("The main window is not visible. It may not be possible to " +
					                                                           "quit {0} using the graphical user interface once the tray icon is removed."),
					                                         MainClass.ApplicationName);
					ResponseType choice = (ResponseType)dialog.Run();
					dialog.Destroy();
					if (choice != ResponseType.Ok)
						return;
				}
				TrayIcon.Visible = false; 
			};
			menu.Append(item);
			
			item = new ImageMenuItem(Stock.Quit, MainWindow.UI.AccelGroup);
			item.Activated += delegate(object sender, EventArgs e) { MainClass.Quit(false); };
			menu.Append(item);
			menu.ShowAll();
			
			return menu;
		}
		
		public static bool IsInitialized
		{
			get { return TrayIcon.icon != null; }
		}
		
		public static bool Visible
		{
			get
			{
				if (TrayIcon.icon_type == TrayIcon.TrayIconType.AppIndicator)
					return TrayIcon.__AppIndicatorVisible;
				else
					return ((StatusIcon)icon).Visible;
			}
			set
			{
				if (TrayIcon.icon_type == TrayIcon.TrayIconType.AppIndicator)
					TrayIcon.__AppIndicatorVisible = value;
				else
					((StatusIcon)icon).Visible = value;
			}
		}
		
		private static bool __AppIndicatorVisible
		{
			get { return ((AppIndicator.ApplicationIndicator)icon).Status == AppIndicator.Status.Active; }
			set { ((AppIndicator.ApplicationIndicator)icon).Status = value ? AppIndicator.Status.Active : AppIndicator.Status.Passive; }
		}
		
		public static string Tooltip
		{
			set
			{
				if (TrayIcon.icon_type == TrayIcon.TrayIconType.AppIndicator)
				{
					if (TrayIcon.indicator_status_label != null)
						TrayIcon.indicator_status_label.Text = value.Replace("\n", "  ");
				}
				else
				{
					((StatusIcon)icon).Tooltip = value;
				}
			}
		}
	}
}
