package de.skyrix.zsp.gui;

import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import javax.swing.UIManager;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

import com.jeans.trayicon.SwingTrayPopup;
import com.jeans.trayicon.TrayIconCallback;
import com.jeans.trayicon.TrayIconException;
import com.jeans.trayicon.WindowsTrayIcon;

import de.skyrix.zsp.event.ProxyStateEvent;
import de.skyrix.zsp.event.ProxyStateListener;
import de.skyrix.zsp.logic.Proxy;
import de.skyrix.zsp.logic.ZidestoreSpider;
import de.skyrix.zsp.logic.cache.CacheManager;

public class SystemTray {
	private static final int DO_REFRESH_CACHE = 1;
	private static final int DO_EMPTY_CACHE = 2;
	private static final int DO_SHOW_OPTIONS = 3;

	private JMenuItem miEmptyCache = null;
	private JMenuItem miOptions = null;
	private JMenuItem miRefreshCache = null;

	protected boolean m_JAWTInit;
	WindowsTrayIcon trayIcon = null;

	public SystemTray() throws TrayIconException, InterruptedException {
		// Set callback method to send windows messages through Tray Icon library
		WindowsTrayIcon.setWindowsMessageCallback(new WindowsMessageCallback());

		trayIcon =
			new WindowsTrayIcon(
				loadImage(
					(Proxy.isOnline() ? "logo_16x16_on.gif" : "logo_16x16_off.gif")),
				16,
				16);

		WindowsTrayIcon.initJAWT();
		createPopup().setTrayIcon(trayIcon);
		trayIcon.setToolTipText(
			"Zidestore proxy server: "
				+ (Proxy.isOnline() ? "online" : "offline")
				+ " mode");

		registerListeners();

		trayIcon.setVisible(true);
	}

	private void registerListeners() {
		final WindowsTrayIcon icon = trayIcon;
		Proxy.addProxyStateLister(new ProxyStateListener() {

			public void proxyStateChanged(ProxyStateEvent e) {
				System.out.println(
					"proxy state changed to " + (e.isOnline() ? "online" : "offline"));

				try {
					icon.setImage(
						loadImage(
							(Proxy.isOnline() ? "logo_16x16_on.gif" : "logo_16x16_off.gif")),
						16,
						16);
					trayIcon.setToolTipText(
						"Zidestore proxy server: "
							+ (Proxy.isOnline() ? "online" : "offline")
							+ " mode");
				}
				catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		});
	}

	public SwingTrayPopup createPopup() {
		SwingTrayPopup popup = new SwingTrayPopup();
		miOptions = new JMenuItem("Options");
		miOptions.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				CommandThread.runCommand(DO_SHOW_OPTIONS);
			}
		});
		popup.add(miOptions);
		popup.addSeparator();

		miEmptyCache = new JMenuItem("Empty cache");
		miEmptyCache.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				CommandThread.runCommand(DO_EMPTY_CACHE);
			}
		});
		popup.add(miEmptyCache);

		miRefreshCache = new JMenuItem("Refresh cache");
		miRefreshCache.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				CommandThread.runCommand(DO_REFRESH_CACHE);
			}
		});
		popup.add(miRefreshCache);

		popup.addSeparator();
		JMenuItem item = new JMenuItem("Shutdown");
		item.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				trayIcon.setVisible(false);
				System.exit(0);
			}
		});
		popup.add(item);

		//		JCheckBoxMenuItem test = new JCheckBoxMenuItem("huhu");
		//    test.setEnabled(false);
		//		sub.add(test);
		//		sub.addSeparator();

		//WindowsTrayIcon.initJAWT();

		//register PopupMenuListener
		popup.addPopupMenuListener(new PopupMenuListener() {

			public void popupMenuCanceled(PopupMenuEvent e) {
				//do nothing
			}

			public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
				//do nothing

			}

			public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
				boolean enableMenu =
					!ZidestoreSpider.isSpiderRunning() && Proxy.isOnline();
          
        miEmptyCache.setEnabled(enableMenu);
        miRefreshCache.setEnabled(enableMenu);
        miOptions.setEnabled(enableMenu);
			}
		});

		return popup;
	}

	public Image loadImage(String fileName) {
		return new ImageIcon(getClass().getResource("images/" + fileName))
			.getImage();
	}

	public static void setLookAndFeel() {
		try {
			UIManager.setLookAndFeel(
				"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		}
		catch (Exception ex) {
		}
	}

	public void initJAWT() {
		if (!m_JAWTInit) {
			WindowsTrayIcon.initJAWT();
			m_JAWTInit = true;
		}
	}

	public static void startSystemTray() {
		try {
			String appName = "ZSP";

			long result = WindowsTrayIcon.sendWindowsMessage(appName, 1234);
			if (result != -1) {
				return;
			}
			WindowsTrayIcon.initTrayIcon(appName);
			new SystemTray();
		}
		catch (TrayIconException e) {
			//System.out.println("Error: " + e.getMessage());
		}
		catch (InterruptedException e) {
		}
	}

	private class WindowsMessageCallback implements TrayIconCallback {
		public int callback(int param) {
			// Param contains the integer value send with sendWindowsMessage(appName,param)
			System.out.println(
				"[Other instance started (parameter: " + param + ")].");
			trayIcon.setVisible(true);

			// Return integer value to other process
			return 4321;
		}
	}

	private static final class CommandThread extends Thread {
		private int command = 0;

		private CommandThread(int command) {
			this.command = command;
		}

		public static void runCommand(int command) {
			CommandThread commandThread = new CommandThread(command);
			commandThread.setPriority(Thread.MIN_PRIORITY);
			commandThread.start();
		}

		public void run() {
			if (ZidestoreSpider.isSpiderRunning()) {
				System.out.println("Spider is running...abort");
				return;
			}

			if (!Proxy.isOnline()) {
				System.out.println("Not in online mode...abort");
				return;
			}

			switch (command) {
				case DO_REFRESH_CACHE :
					try {
						ZidestoreSpider.getInstance().runSpiderOnce();
					}
					catch (Exception ex) {
					}
					break;
				case DO_EMPTY_CACHE :
					CacheManager.getInstance().clearCache();
					break;
				case DO_SHOW_OPTIONS :
					ConfigDialog configDialog = new ConfigDialog();
					configDialog.pack();
					configDialog.show();
					break;
			}
		}
	}
}
