// 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.QuickStep.Integration
{

    public static 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
                TrayIcon.InitializeAppIndicator();
                TrayIcon.icon_type = TrayIcon.TrayIconType.AppIndicator;
            }
            catch (Exception)
            {
                // fall back to Gtk.StatusIcon
                TrayIcon.InitializeStatusIcon();
                TrayIcon.icon_type = TrayIcon.TrayIconType.StatusIcon;
            }
        }
        
        public static void SetTooltip(int shared, int connected)
        {
            if (TrayIcon.IsInitialized == false)
                return;
                
            TrayIcon.Tooltip = string.Format(Catalog.GetString("Remote access:\n{0} shared\n{1} connected"),
                                             shared,
                                             connected);
        }

        private static void InitializeAppIndicator()
        {
            var indicator = new AppIndicator.ApplicationIndicator("hiperscan.quickstep",
                                                                  "quickstep",
                                                                  AppIndicator.Category.ApplicationStatus)
            {
                Status = AppIndicator.Status.Attention,
                Menu = TrayIcon.CreateMenu(TrayIconType.AppIndicator)
            };
            TrayIcon.icon = indicator;
            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 += (o, 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 += (sender, 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
                {
                    TrayIcon.indicator_status_label
                };
                menu.Append(item);

                TrayIcon.indicator_visible_item = new CheckMenuItem(Catalog.GetString("_Show QuickStep"))
                {
                    Active = MainClass.MainWindow.Visible
                };
                TrayIcon.indicator_visible_item.Toggled += (sender, 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 += (sender, e) =>
            {
                if (MainClass.MainWindow.Visible == false)
                {
                    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);
                    var 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 += (sender, e) => MainClass.Quit(false);
            menu.Append(item);
            menu.ShowAll();
            
            return menu;
        }

        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;
                }
            }
        }

        public static bool IsInitialized => TrayIcon.icon != null;
    }
}