// This file is a part of the xMule Project.
//
// Copyright (c) 2004 Theodore R. Smith (hopeseekr@xmule.ws / http://www.xmule.ws/)
// DSA-1024 Fingerprint: 10A0 6372 9092 85A2 BB7F 907B CB8B 654B E33B F1ED
//
// Copyright(C)2002 Tiku & Patrizio Bassi aka Hetfield <hetfield@email.it>
//
// 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 2 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, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifndef __SYSTRAY_DISABLED__

#ifdef PRECOMP
    #include "xmule-headers.h"
#endif

#include "SysTray.h"                        // Needed for this Interface's Prototype

#include "config.h"                         // Needed for VERSION
#include "eggtrayicon.h"                    // Needed for egg_tray_icon_new
#include "NewFunctions.h"                   // Needed for MAP
#include "opcodes.h"                        // Needed for UNLIMITED
#include "otherfunctions.h"                 // Needed for GetResString
#include "Preferences.h"                    // CPreferences::GetUserHash
#include "resource.h"                       // Needed for IDS_CONNECTING
#include "server.h"                         // Needed for CServer
#include "SharedFileList.h"                 // Needed for CSharedFileList
#include "sockets.h"                        // Needed for CServerConnect
#include "UploadQueue.h"                    // Needed for CUploadQueue
#include "xmule.h"                          // Needed for theApp
#include "xmuleDlg.h"                       // Needed for theApp.xmuledlg

#include <arpa/inet.h>                      // Needed for inet_ntoa
#include <gtk/gtk.h>                        // Needed for gtk_menu_new
#include <libintl.h>                        // Needed for bindtextdomain
#include <net/if.h>                         // Needed for ifreq
#include <netinet/in.h>                     // Needed for sockaddr_in
#include <sys/ioctl.h>                      // Needed for SIOCGIFADDR
#include <X11/Xatom.h>                      // Needed for XA_WINDOW
#include <deque>                            // Needed for std::deque

#ifdef __WXMAC__
    #include <sys/types.h>
    #include <sys/socket.h>
#endif

#include <DynPrefs/DynPrefs.h>              // Needed for DynamicPreferences

#include "pixmaps/mule_Tr_grey.ico.xpm"

#ifdef __SAFE_TRAY__
gchar *getIP()
{
    gchar *ip = "Detection Disabled";
    return ip;
}

#endif

std::deque<int> m_pLimits;
std::deque<COLORREF> m_pColors;

#ifndef __SAFE_TRAY__
gchar *getIP()
{
    static gchar* ip = 0;

    if (ip == 0)
    {
        wxString interface;
        int index;
        index = 0;
        int sfd;
        struct ifreq ifr;
        struct sockaddr_in *sin = (struct sockaddr_in *) &ifr.ifr_addr;
        memset( &ifr, 0, sizeof ifr);
        sfd = socket(AF_INET, SOCK_STREAM, 0);
        strcpy(ifr.ifr_name, "ppp0");
        sin->sin_family = AF_INET;

        if (0 == ioctl(sfd, SIOCGIFADDR, &ifr))
        {
            ip = inet_ntoa(sin->sin_addr);

            return ip;
        }
        else
        {
            printf("Not connected at network with ppp0 direct connection\n");

            do
            {
                interface << "eth" << index;
                strcpy(ifr.ifr_name, interface);
                sin->sin_family = AF_INET;

                if (ioctl(sfd, SIOCGIFADDR, &ifr) == 0)
                {
                    ip = inet_ntoa(sin->sin_addr);
                    index++;
                }
                else
                {
                    interface << "Not connected at network with " << interface;
                    printf(interface.c_str());
                }
            }
            while (0 == ioctl(sfd, SIOCGIFADDR, &ifr));
        }
    }

    return ip;
}

#endif
#include <iostream>
using namespace std;
// Same check of the connection tab.
void speed_check()
{
    if (theApp.dynprefs->Get<long>("capacities-download") < theApp.dynprefs->Get<long>("limits-download"))
    {
        theApp.dynprefs->Add("limits-download", UNLIMITED);
    }

    if (theApp.dynprefs->Get<long>("capacities-upload") < theApp.dynprefs->Get<long>("limits-upload"))
    {
        theApp.dynprefs->Add("limits-upload", UNLIMITED);
    }

    long int max_upload = theApp.dynprefs->Get<long>("limits-upload");
    if (max_upload != UNLIMITED)
    {
        cout << "Unlimited: " << UNLIMITED << " | limits-upload: " << max_upload << endl;
        if ((max_upload < 4) && (max_upload * 3 < theApp.dynprefs->Get<long>("limits-download")))
        {
            theApp.dynprefs->Add("limits-download", max_upload * 3);
        }
        else if ((max_upload < 10) && (max_upload * 4 < theApp.dynprefs->Get<long>("limits-download")))
        {
            theApp.dynprefs->Add("limits-download", max_upload * 4);
        }
    }
}

// Closes xMule
void close_xmule()
{
    wxCloseEvent SendCloseEvent;
    theApp.xmuledlg->OnClose(SendCloseEvent);
}

// Hides xMule
void hide_xmule()
{
    if (theApp.xmuledlg->IsShown())
    {
        theApp.xmuledlg->Show(FALSE);
    }
}

// Shows xMule
void show_xmule()
{
    if (!theApp.xmuledlg->IsShown())
    {
        theApp.xmuledlg->Show(TRUE);
    }
}

// Shows or hides xMule...double click automatic selection
void showgui()
{
    if (theApp.xmuledlg->IsShown())
    {
        theApp.xmuledlg->Iconize(TRUE);
        theApp.xmuledlg->Show(FALSE);
    }
    else
    {
        theApp.xmuledlg->Show(TRUE);
    }
}

// Set download and upload speed to max
void set_all_max()
{
    theApp.dynprefs->Add("limits-upload", theApp.dynprefs->Get<long>("capacities-upload"));
    theApp.dynprefs->Add("limits-download", theApp.dynprefs->Get<long>("capacities-download"));
}

// Set download and upload speed to min
void set_all_min()
{
    theApp.dynprefs->Add("limits-download", 2L);
    theApp.dynprefs->Add("limits-upload", 2L);
    speed_check();
}

// Connect to a server
void connect_any_server()
{
    if (theApp.serverconnect->IsConnected())
    {
        theApp.serverconnect->Disconnect();
    }
    theApp.xmuledlg->AddLogLine(true, GetResString(IDS_CONNECTING));
    theApp.serverconnect->ConnectToAnyServer();
    theApp.xmuledlg->ShowConnectionState(false);
}

// Disconnect
void disconnect()
{
    if (theApp.serverconnect->IsConnected())
    {
        theApp.serverconnect->Disconnect();
    }
    else
    {
        printf("Already disconnected!\n");
    }
}

// Set download speed
void set_dl_speed(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
    long temp;
    temp = atol(g_strdup_printf("%s", gtk_object_get_data(GTK_OBJECT(widget), "label")));
    if (temp == 0)
    {
        theApp.dynprefs->Add("limits-download", UNLIMITED);
    }
    else
    {
        theApp.dynprefs->Add("limits-download", temp);
    }
    speed_check();
}

// Set upload speed
void set_up_speed(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
    long temp;
    temp = atol(g_strdup_printf("%s", gtk_object_get_data(GTK_OBJECT(widget), "label")));
    if (temp == 0)
    {
        theApp.dynprefs->Add("limits-upload", UNLIMITED);
    }
    else
    {
        theApp.dynprefs->Add("limits-upload", temp);
    }
    speed_check();
}

// Create menu linked to the tray icon
static gboolean tray_menu(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
    // Sets gtk objects
    GtkWidget *status_menu, *item, *down_speed, *dl_item, *up_speed, *up_item, *info_menu, *info_item;
    wxString label;
    wxString upl_speed, dl_speed;
    gchar *temp, *tempstring;
    int tempspeed;
    uint16_t max_dl_speed, max_up_speed;
    uint16_t actual_dl_speed, actual_up_speed;
    speed_check();
    actual_up_speed = theApp.dynprefs->Get<long>("limits-upload");
    actual_dl_speed = theApp.dynprefs->Get<long>("limits-download");
    max_up_speed = theApp.dynprefs->Get<long>("capacities-upload");
    max_dl_speed = theApp.dynprefs->Get<long>("capacities-download");
    // What will be shown, very nice!
    if (actual_dl_speed == UNLIMITED || actual_dl_speed == 0)
    {
        dl_speed = "Unlimited";
    }
    else
    {
        temp = g_strdup_printf("%d", actual_dl_speed);
        dl_speed = temp;
    }
    if (actual_up_speed == UNLIMITED || actual_up_speed == 0)
    {
        upl_speed = "Unlimited";
    }
    else
    {
        temp = g_strdup_printf("%d", actual_up_speed);
        upl_speed = temp;
    }
    if (max_dl_speed == UNLIMITED || max_dl_speed == 0)
    {
        max_dl_speed = 100;
    }
    if (max_up_speed == UNLIMITED || max_up_speed == 0)
    {
        max_up_speed = 100;
    }
    label = "xMule " + wxString(PACKAGE_VERSION) + "\nActual Speed Limits:\nDL: " + dl_speed + " kb/s " + "UP:" + upl_speed + " kb/s";
    // Info menu
    info_menu = gtk_menu_new();
    gtk_menu_set_title(GTK_MENU(info_menu), "xMule TrayMenu Info");

    if (theApp.dynprefs->Get<wxString>("nickname").IsEmpty() != true)
    {
        info_item = gtk_menu_item_new_with_label(wxT("Nick: ") + theApp.dynprefs->Get<wxString>("nickname"));
    }
    else
    {
        info_item = gtk_menu_item_new_with_label("Nick: Not Ready");
    }
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    if (theApp.glob_prefs->GetUserHash())
    {
        wxString hash;
        hash = EncodeBase16((const unsigned char *) theApp.glob_prefs->GetUserHash(), 16);
        info_item = gtk_menu_item_new_with_label(wxString("Hash: ") + hash.c_str());
    }
    else
    {
        info_item = gtk_menu_item_new_with_label("Hash: Not Ready");
    }
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    if (theApp.serverconnect->IsConnected())
    {
        info_item = gtk_menu_item_new_with_label(wxString("ClientID: ") + wxString::Format("%.0f", (float) theApp.serverconnect->GetClientID()));
    }
    else
    {
        info_item = gtk_menu_item_new_with_label("ID: Not Connected");
    }
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    tempstring = getIP();
    info_item = gtk_menu_item_new_with_label(wxString("IP: ") + tempstring);
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);

    tempstring = g_strdup_printf("%d", theApp.dynprefs->Get<long>("tcp-port"));
    info_item = gtk_menu_item_new_with_label(wxString("TCP Port: ") + tempstring);

    gtk_container_add(GTK_CONTAINER(info_menu), info_item);

    long udp_port(theApp.dynprefs->Get<long>("udp-port"));
    if (udp_port)
    {
        tempstring = g_strdup_printf("%d", udp_port);
        info_item = gtk_menu_item_new_with_label(wxString("UDP Port: ") + tempstring);
    }
    else
    {
        info_item = gtk_menu_item_new_with_label("UDP Port: Not Ready");
    }

    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    if (theApp.dynprefs->Get<bool>("online-signature") == true)
    {
        info_item = gtk_menu_item_new_with_label("Online Signature: Enabled");
    }
    else
    {
        info_item = gtk_menu_item_new_with_label("Online Signature: Disabled");
    }
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    if (theApp.Start_time > 0)
    {
        DWORD running;
        running = (GetTickCount() - theApp.Start_time) / 1000;
        tempstring = g_strdup_printf("%s", CastSecondsToHM(running) .GetData());
        info_item = gtk_menu_item_new_with_label(wxString("Uptime: ") + tempstring);
    }
    else
    {
        info_item = gtk_menu_item_new_with_label("Uptime: None");
    }
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    if (theApp.serverconnect->GetCurrentServer() != NULL)
    {
        info_item = gtk_menu_item_new_with_label(wxString("ServerName: ") + theApp.serverconnect->GetCurrentServer()->GetListName());
        gtk_container_add(GTK_CONTAINER(info_menu), info_item);
        tempstring = g_strdup_printf("%d", theApp.serverconnect->GetCurrentServer()->GetPort());
        info_item = gtk_menu_item_new_with_label(wxString("ServerIP: ") + theApp.serverconnect->GetCurrentServer()->GetFullIP() + wxString(" : ") + tempstring);
        gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    }
    else
    {
        info_item = gtk_menu_item_new_with_label("ServerName: Not Connected");
        gtk_container_add(GTK_CONTAINER(info_menu), info_item);
        info_item = gtk_menu_item_new_with_label("ServerIP: Not Connected");
        gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    }
//    tempstring = g_strdup_printf("%d", theApp.sharedfiles->listof_SharedFiles->Data);
    info_item = gtk_menu_item_new_with_label(wxString("Shared Files: ") + tempstring);
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    tempstring = g_strdup_printf("%d", theApp.uploadqueue->GetWaitingUserCount());
    info_item = gtk_menu_item_new_with_label(wxString("Queued Clients: ") + tempstring);
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    tempstring = g_strdup_printf("%.2f", ((float)(theApp.stat_sessionReceivedBytes + theApp.glob_prefs->GetTotalDownloaded()) / 1073741824));
    info_item = gtk_menu_item_new_with_label(wxString("Total DL: ") + tempstring + wxString("  GB"));
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    tempstring = g_strdup_printf("%.2f", ((float)(theApp.stat_sessionSentBytes + theApp.glob_prefs->GetTotalUploaded()) / 1073741824));
    info_item = gtk_menu_item_new_with_label(wxString("Total UP: ") + tempstring + wxString("  GB"));
    gtk_container_add(GTK_CONTAINER(info_menu), info_item);
    // Main menu
    status_menu = gtk_menu_new();
    gtk_menu_set_title(GTK_MENU(status_menu), "xMule Tray Menu");
    // First item, not linked, only to show version and speed
    item = gtk_menu_item_new_with_label(label);
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Personal infos item, not linked, only to show them
    item = gtk_menu_item_new_with_label("Personal Infos");
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), info_menu);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Download speed submenu
    down_speed = gtk_menu_new();
    temp = "Unlimited";
    dl_item = gtk_menu_item_new_with_label(temp);
    gtk_object_set_data_full(GTK_OBJECT(dl_item), "label", 0, NULL);
    gtk_container_add(GTK_CONTAINER(down_speed), dl_item);
    gtk_signal_connect(GTK_OBJECT(dl_item), "activate", GTK_SIGNAL_FUNC(set_dl_speed), dl_item);
    tempspeed = max_dl_speed;
    temp = g_strdup_printf("%d", tempspeed);
    dl_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(down_speed), dl_item);
    gtk_object_set_data_full(GTK_OBJECT(dl_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(dl_item), "activate", GTK_SIGNAL_FUNC(set_dl_speed), dl_item);
    tempspeed = (max_dl_speed / 5) *4;
    temp = g_strdup_printf("%d", tempspeed);
    dl_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(down_speed), dl_item);
    gtk_object_set_data_full(GTK_OBJECT(dl_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(dl_item), "activate", GTK_SIGNAL_FUNC(set_dl_speed), dl_item);
    tempspeed = (max_dl_speed / 5) *3;
    temp = g_strdup_printf("%d", tempspeed);
    dl_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(down_speed), dl_item);
    gtk_object_set_data_full(GTK_OBJECT(dl_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(dl_item), "activate", GTK_SIGNAL_FUNC(set_dl_speed), dl_item);
    tempspeed = (max_dl_speed / 5) *2;
    temp = g_strdup_printf("%d", tempspeed);
    dl_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(down_speed), dl_item);
    gtk_object_set_data_full(GTK_OBJECT(dl_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(dl_item), "activate", GTK_SIGNAL_FUNC(set_dl_speed), dl_item);
    tempspeed = (max_dl_speed / 5);
    temp = g_strdup_printf("%d", tempspeed);
    dl_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(down_speed), dl_item);
    gtk_object_set_data_full(GTK_OBJECT(dl_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(dl_item), "activate", GTK_SIGNAL_FUNC(set_dl_speed), dl_item);
    // Upload speed submenu
    up_speed = gtk_menu_new();
    temp = "Unlimited";
    up_item = gtk_menu_item_new_with_label(temp);
    gtk_object_set_data_full(GTK_OBJECT(up_item), "label", 0, NULL);
    gtk_container_add(GTK_CONTAINER(up_speed), up_item);
    gtk_signal_connect(GTK_OBJECT(up_item), "activate", GTK_SIGNAL_FUNC(set_up_speed), up_item);
    tempspeed = max_up_speed;
    temp = g_strdup_printf("%d", tempspeed);
    up_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_object_set_data_full(GTK_OBJECT(up_item), "label", temp, NULL);
    gtk_container_add(GTK_CONTAINER(up_speed), up_item);
    gtk_signal_connect(GTK_OBJECT(up_item), "activate", GTK_SIGNAL_FUNC(set_up_speed), up_item);
    tempspeed = (max_up_speed / 5) *4;
    temp = g_strdup_printf("%d", tempspeed);
    up_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(up_speed), up_item);
    gtk_object_set_data_full(GTK_OBJECT(up_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(up_item), "activate", GTK_SIGNAL_FUNC(set_up_speed), up_item);
    tempspeed = (max_up_speed / 5) *3;
    temp = g_strdup_printf("%d", tempspeed);
    up_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(up_speed), up_item);
    gtk_object_set_data_full(GTK_OBJECT(up_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(up_item), "activate", GTK_SIGNAL_FUNC(set_up_speed), up_item);
    tempspeed = (max_up_speed / 5) *2;
    temp = g_strdup_printf("%d", tempspeed);
    up_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(up_speed), up_item);
    gtk_object_set_data_full(GTK_OBJECT(up_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(up_item), "activate", GTK_SIGNAL_FUNC(set_up_speed), up_item);
    tempspeed = (max_up_speed / 5);
    temp = g_strdup_printf("%d", tempspeed);
    up_item = gtk_menu_item_new_with_label(wxString(temp) + " kb/s");
    gtk_container_add(GTK_CONTAINER(up_speed), up_item);
    gtk_object_set_data_full(GTK_OBJECT(up_item), "label", temp, NULL);
    gtk_signal_connect(GTK_OBJECT(up_item), "activate", GTK_SIGNAL_FUNC(set_up_speed), up_item);
    // Show item
    item = gtk_menu_item_new_with_label(_("Show"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(show_xmule), NULL);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Hide item
    item = gtk_menu_item_new_with_label(_("Hide"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(hide_xmule), NULL);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Sets max speed
    item = gtk_menu_item_new_with_label(_("All To Max Speed"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(set_all_max), NULL);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Sets min speed
    item = gtk_menu_item_new_with_label(_("All To Min Speed"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(set_all_min), NULL);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Download Speed item
    item = gtk_menu_item_new_with_label(_("Download Limit"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), down_speed);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Upload Speed item
    item = gtk_menu_item_new_with_label(_("Upload Limit"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), up_speed);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Connect item
    item = gtk_menu_item_new_with_label(_("Connect to any server"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(connect_any_server), NULL);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    // Disconnection Speed item
    item = gtk_menu_item_new_with_label(_("Disconnect from server"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(disconnect), NULL);
    // Separator
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    //Exit item
    item = gtk_menu_item_new_with_label(_("Exit"));
    gtk_container_add(GTK_CONTAINER(status_menu), item);
    gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(close_xmule), NULL);
    // When the menu is popped - down, you need to destroy it
    gtk_signal_connect(GTK_OBJECT(status_menu), "selection - done", GTK_SIGNAL_FUNC(gtk_widget_destroy), &status_menu);
    // gtk_signal_connect(GTK_OBJECT(info_menu), "leave_notify_event", GTK_SIGNAL_FUNC(gtk_widget_destroy), &info_menu);
    // Finalization
    gtk_widget_show_all(status_menu);
    gtk_menu_popup(GTK_MENU(status_menu), NULL, NULL, NULL, NULL, event->button, event->time);
    return TRUE;
}

static gboolean tray_clicked(GtkWidget *event_box, GdkEventButton *event, gpointer data)
{
    // Mouse wheel or middle click + left double click
    if ((event->button == 1 &&event->type == GDK_2BUTTON_PRESS) || event->button == 2)
    {
        showgui();
        return true;
    }
    // Mouse right click
    if (event->button == 3)
    {
        return tray_menu(event_box, event, data);
    }
}

#endif

CSysTray::CSysTray(wxWindow *_parent, int _desktopMode, const wxString &title)
{
#ifndef __SYSTRAY_DISABLED__
    static GtkWidget *eventbox;
    gdk_rgb_init();
    m_sDimensions.cx = 16;
    m_sDimensions.cy = 16;
    m_nSpacingWidth = 1;
    m_nNumBars = 1;
    m_nMaxVal = 100;
    parent = _parent;
    desktopMode = _desktopMode;
    if (desktopMode == 3)
    {
        // Not wanted, so don't show it.
        return;
    }
    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE_NAME, LOCALEDIR);
    textdomain(PACKAGE_NAME);
    bool use_legacy = false;
    // Case 2 and 3 are KDE/other legacy system
    if (desktopMode == 1 || desktopMode == 2)
    {
        use_legacy = true;
    }
    if (use_legacy)
    {
        status_docklet = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(status_docklet), title);
        gtk_window_set_wmclass(GTK_WINDOW(status_docklet), "xmule_StatusDocklet", "xMule");
        gtk_widget_set_usize(status_docklet, 22, 22);
    }
    else
    {
        status_docklet = GTK_WIDGET(egg_tray_icon_new(_("xMule for Linux")));
        if (status_docklet == NULL)
        {
            printf("**** WARNING: Can't create status docklet. Systray will not be created.\n");
            desktopMode = 4;
            return;
        }
    }
    gtk_widget_realize(status_docklet);
    gtk_signal_connect(GTK_OBJECT(status_docklet), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &status_docklet);
    // Set image
    GdkBitmap *mask = NULL;
    GdkPixmap *
    img = gdk_pixmap_create_from_xpm_d(status_docklet->window, &mask, NULL, mule_Tr_grey_ico);
    status_image = gtk_pixmap_new(img, mask);
    eventbox = gtk_event_box_new();
    gtk_widget_show(eventbox);
    gtk_container_add(GTK_CONTAINER(eventbox), status_image);
    gtk_container_add(GTK_CONTAINER(status_docklet), eventbox);
    gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event", GTK_SIGNAL_FUNC(tray_clicked), NULL);
    gtk_signal_connect(GTK_OBJECT(status_image), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &status_image);
    // Set tooltips
    status_tooltips = gtk_tooltips_new();
    gtk_tooltips_enable(status_tooltips);
    gtk_tooltips_set_tip(status_tooltips, status_docklet, _("xMule for Linux"), "blind text");
    // Finalization
    gtk_widget_show(status_image);
    if (use_legacy)
    {
        setupProperties();
    }
    gtk_widget_show(GTK_WIDGET(status_docklet));
    gtk_widget_show_all(GTK_WIDGET(status_docklet));
#endif
}

void CSysTray::setupProperties()
{
#ifndef __SYSTRAY_DISABLED__
    GdkWindow *window = status_docklet->window;
    glong data[1];
    GdkAtom kwm_dockwindow_atom;
    GdkAtom kde_net_system_tray_window_for_atom;
    kwm_dockwindow_atom = gdk_atom_intern("KWM_DOCKWINDOW", FALSE);
    kde_net_system_tray_window_for_atom = gdk_atom_intern("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", FALSE);
    /* This is the old KDE 1.0 and GNOME 1.2 way... */
    data[0] = TRUE;
    gdk_property_change(window, kwm_dockwindow_atom, kwm_dockwindow_atom, 32, GDK_PROP_MODE_REPLACE, (guchar *) &data, 1);
    /* This is needed to support KDE 2.0 */
    /* can be set to zero or the root win I think */
    data[0] = 0;
    gdk_property_change(window, kde_net_system_tray_window_for_atom, (GdkAtom) XA_WINDOW, 32, GDK_PROP_MODE_REPLACE, (guchar *) &data, 1);
#endif
}

void CSysTray::Show(const wxChar *caption, int nMsgType, DWORD dwTimeToShow, DWORD dwTimeToStay, DWORD dwTimeTOHide)
{
#ifndef __SYSTRAY_DISABLED__
    if (desktopMode == 4)
    {
        return;
    }
    if (status_docklet == NULL)
    {
        return;
    }
    gtk_tooltips_set_tip(status_tooltips, status_docklet, caption, NULL);
#endif
}

void CSysTray::TraySetToolTip(char *data)
{
#ifndef __SYSTRAY_DISABLED__
    if (desktopMode == 4)
    {
        return;
    }
    if (status_docklet == NULL)
    {
        return;
    }
    gtk_tooltips_set_tip(status_tooltips, status_docklet, data, NULL);
#endif
}

// It the nLevel is greater than the values defined in m_pLimits the last value in the array is used
COLORREF CSysTray::GetMeterColor(int nLevel)
{
#ifndef __SYSTRAY_DISABLED__
    for (int i = 0 ; i < m_nEntries ; i++)
    {
        if (nLevel <= m_pLimits[i])
        {
            return m_pColors[i];
        }
    }
#else
    m_pColors[m_nEntries - 1] = 0;
#endif
    return m_pColors[m_nEntries - 1];
}

void CSysTray::DrawIconMeter(GdkPixmap *pix, GdkBitmap *mask, int nLevel, int nPos)
{
#ifndef __SYSTRAY_DISABLED__
    GdkGC *gc = gdk_gc_new(pix);
    gdk_rgb_gc_set_background(gc, 0);
    // Border color is black :)
    gdk_rgb_gc_set_foreground(gc, GetMeterColor(nLevel));
    gdk_draw_rectangle(pix, gc, 1, ((m_sDimensions.cx - 1) / m_nNumBars) *nPos + m_nSpacingWidth, m_sDimensions.cy - ((nLevel * (m_sDimensions.cy - 1) / m_nMaxVal) + 1), ((m_sDimensions.cx - 1) / m_nNumBars) * (nPos + 1) + 1, m_sDimensions.cy);
    // Then draw to mask (look! it must be initialised even if it is not used!)
    GdkGC *newgc = gdk_gc_new(mask);
    gdk_rgb_gc_set_foreground(newgc, 0x0);
    gdk_draw_rectangle(mask, newgc, TRUE, 0, 0, 22, 22);
    if (nLevel > 0)
    {
        gdk_rgb_gc_set_foreground(newgc, 0xffffff);
        gdk_draw_rectangle(mask, newgc, 1, m_sDimensions.cx - 2, m_sDimensions.cy - ((nLevel * (m_sDimensions.cy - 1) / m_nMaxVal) + 1), m_sDimensions.cx, m_sDimensions.cy);
    }
    gdk_gc_unref(newgc);
    gdk_gc_unref(gc);
#endif
}

void CSysTray::drawMeters(GdkPixmap *pix, GdkBitmap *mask, int *pBarData)
{
#ifndef __SYSTRAY_DISABLED__
    if (pBarData == NULL)
    {
        return;
    }
    for (int i = 0 ; i < m_nNumBars ; i++)
    {
        DrawIconMeter(pix, mask, pBarData[i], i);
    }
#endif
}

void CSysTray::TraySetIcon(char **data, bool what, int *pVals)
{
#ifndef __SYSTRAY_DISABLED__
    if (desktopMode == 4)
    {
        return;
    }
    if (status_image == NULL)
    {
        // There is nothing you can do..:
        return;
    }
    GdkPixmap *oldpix, *oldbit;
    GdkPixmap *newpix, *newbit;
    /* Set new picture */
    gtk_pixmap_get(GTK_PIXMAP(status_image), &oldpix, &oldbit);
    newpix = gdk_pixmap_create_from_xpm_d(status_docklet->window, &newbit, NULL, data);
    /* Create pixmap for meters */
    GdkPixmap *meterpix = gdk_pixmap_new(status_docklet->window, 22, 22, - 1);
    GdkBitmap *meterbit = gdk_pixmap_new(status_docklet->window, 22, 22, 1);
    /* Draw meters */
    drawMeters(meterpix, meterbit, pVals);
    /* Then draw meters onto main pix */
    GdkGC *mygc = gdk_gc_new(newpix);
    gdk_gc_set_clip_mask(mygc, meterbit);
    gdk_draw_pixmap(newpix, mygc, meterpix, 0, 0, 0, 0, 22, 22);
    gdk_gc_set_clip_mask(mygc, NULL);
    gdk_gc_unref(mygc);
    /* Finally combine masks */
    mygc = gdk_gc_new(newbit);
    gdk_gc_set_function(mygc, GDK_OR);
    gdk_draw_pixmap(newbit, mygc, meterbit, 0, 0, 0, 0, 22, 22);
    gdk_gc_unref(mygc);
    gdk_pixmap_unref(meterpix);
    gdk_bitmap_unref(meterbit);
    gtk_pixmap_set(GTK_PIXMAP(status_image), newpix, newbit);
    /* Free old */
    gdk_pixmap_unref(oldpix);
    gdk_bitmap_unref(oldbit);
    /* And force repaint */
    gtk_widget_draw(status_docklet, NULL);
#endif
}

bool CSysTray::SetColorLevels(int *pLimits, COLORREF *pColors, int nEntries)
{
#ifndef __SYSTRAY_DISABLED__
    for (int i = 0 ; i < nEntries ; i++)
    {
        m_pLimits[i] = pLimits[i];
        m_pColors[i] = pColors[i];
    }
    m_nEntries = nEntries;
#endif
    return true;
}

