package in.cdac.medinfo.csnotk.launch;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Image;
import java.awt.SystemColor;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Properties;
import java.util.Set;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JTextPane;

import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.webapp.WebAppContext;

import in.cdac.medinfo.csnotk.csnolib.agents.SNOMEDAgent;

public class Launcher extends Thread {

	static Server server;
	URI url_open;
	private JFrame frmCsnofinderService;
	private JTextField textPort;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Launcher window = new Launcher();
					window.frmCsnofinderService.setVisible(true);

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public Launcher() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmCsnofinderService = new JFrame();
		frmCsnofinderService.getContentPane().setForeground(Color.BLUE);
		frmCsnofinderService.setIconImage(Toolkit.getDefaultToolkit()
				.getImage(Launcher.class.getClassLoader().getResource("CSNOFinder-logo_256_4.png"))
				.getScaledInstance(60, 60, Image.SCALE_DEFAULT));

		frmCsnofinderService.setForeground(SystemColor.textHighlight);

		frmCsnofinderService.setResizable(false);
		frmCsnofinderService.setTitle("CSNOFinder Service");
		frmCsnofinderService.getContentPane().setBackground(Color.WHITE);
		frmCsnofinderService.getContentPane().setFont(new Font("Tahoma", Font.PLAIN, 14));
		frmCsnofinderService.setBounds(100, 100, 450, 300);
		frmCsnofinderService.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		frmCsnofinderService.getContentPane().setLayout(null);
		frmCsnofinderService.setLocationRelativeTo(null);

		JLabel lblPort = new JLabel("Port");
		lblPort.setFont(new Font("Tahoma", Font.PLAIN, 17));
		lblPort.setBounds(115, 91, 53, 30);
		frmCsnofinderService.getContentPane().add(lblPort);

		textPort = new JTextField();
		textPort.setFont(new Font("Tahoma", Font.PLAIN, 17));
		textPort.setToolTipText("Enter Available Port Number");
		textPort.setText("8080");
		textPort.setBounds(156, 94, 154, 25);
		frmCsnofinderService.getContentPane().add(textPort);
		textPort.setColumns(10);

		JPanel panel = new JPanel();
		panel.setBackground(Color.WHITE);
		panel.setBounds(10, 198, 424, 30);
		frmCsnofinderService.getContentPane().add(panel);

		final JTextPane lblURL = new JTextPane();
		lblURL.setForeground(new Color(66, 139, 202));
		lblURL.setFont(new Font("Tahoma", Font.BOLD | Font.ITALIC, 14));
		lblURL.setEditable(false);
		panel.add(lblURL);

		final JButton btnStart = new JButton("START");
		btnStart.setBackground(new Color(66, 139, 202));
		btnStart.setForeground(SystemColor.textHighlightText);
		btnStart.setFont(new Font("Tahoma", Font.PLAIN, 17));

		btnStart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				btnStart.setFocusable(false);
				JFrame jframe = new JFrame();
				if (arg0.getActionCommand().equalsIgnoreCase("START")) {
					Thread serverThread = new Thread(new Launcher(), "CSNOFinderService");

					if (!isCSNOServiceRunning()) {
						String strPort = textPort.getText();
						int port = 0;
						try {
							port = Integer.parseInt(strPort);
						} catch (NumberFormatException ex) {
						}
						if ((port <= 0) || (port > 65535)) {
							JOptionPane.showMessageDialog(jframe, "Enter Correct Port Number", "Invalid Port",
									JOptionPane.ERROR_MESSAGE);
						} else if (isAvailable(port)) {
							server = new Server(port);
							serverThread.start();
							textPort.setEditable(false);
							btnStart.setActionCommand("STOP");
							btnStart.setText("STOP");
							btnStart.setBackground(new Color(255, 0, 0));
							// check the sys-prop and host the url as it is
							String uri = getURIFromPropertiesFile();
							try {
								url_open = new URI("http://localhost:" + port + "/" + uri);

								lblURL.setText(url_open.toString());
								lblURL.setCursor(new Cursor(Cursor.HAND_CURSOR));
								lblURL.addMouseListener(new MouseAdapter() {
									@Override
									public void mouseClicked(MouseEvent e) {
										try {
											Desktop.getDesktop().browse(url_open);

										} catch (IOException e1) {
											// TODO Auto-generated catch block
											e1.printStackTrace();
										}

									}
								});

								if (Desktop.isDesktopSupported()) {
									Desktop.getDesktop().browse(url_open);
								}
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}

						} else {
							JOptionPane.showMessageDialog(jframe, "Port is not available", "Busy Port",
									JOptionPane.ERROR_MESSAGE);
						}
					} else {
						JOptionPane.showMessageDialog(jframe, "CSNOFinder Service is already running.",
								"Already Running", JOptionPane.ERROR_MESSAGE);
					}
				} else if (arg0.getActionCommand().equalsIgnoreCase("STOP")) {
					try {
						server.stop();
					} catch (Exception e) {
						e.printStackTrace();
					}
					lblURL.setText("");
					textPort.setEditable(true);
					btnStart.setText("START");
					btnStart.setActionCommand("START");
					btnStart.setBackground(new Color(66, 139, 202));
				}
			}


			private String getURIFromPropertiesFile() {
				try {
					Properties prop = new Properties();
					InputStream input = new FileInputStream(new File(getURIFromPropertiesFileGeneric(true)));
					prop.load(input);
					if (prop.getProperty("config.flag") != null && prop.getProperty("config.flag").equals("true")) {
						return "csnoserv";
					}
					return "csnofinder";
				} catch (Exception e) {
					System.out.println(e.getMessage());
				}
				return "csnoserv";
			}

			private boolean isAvailable(int port) {
				try (Socket ignored = new Socket("localhost", port)) {
					return false;
				} catch (IOException ignored) {
					return true;
				}
			}
		});
		btnStart.setBounds(115, 144, 195, 30);
		frmCsnofinderService.getContentPane().add(btnStart);
		JPanel headPanel = new JPanel();
		headPanel.setBackground(Color.WHITE);
		JLabel csnoFinderLogo = new JLabel();
		csnoFinderLogo.setIcon(new ImageIcon(
				(Toolkit.getDefaultToolkit().getImage(Launcher.class.getClassLoader().getResource("CSNOFinder.png"))
						.getScaledInstance(100, 47, Image.SCALE_DEFAULT))));
		headPanel.add(csnoFinderLogo);
		headPanel.setBounds(10, 11, 424, 57);
		frmCsnofinderService.getContentPane().add(headPanel);
		frmCsnofinderService.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				if (isCSNOServiceRunning()) {
					try {
						server.stop();
					} catch (Exception e1) {
						e1.printStackTrace();
					}
					System.out.println("Server Stopped");
				}
				frmCsnofinderService.dispose();
				System.exit(0);
			}
		});

	}

	public boolean isCSNOServiceRunning() {
		boolean alreadyRunning = false;
		Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
		for (Thread t : threadSet) {
			if (t.getName().equalsIgnoreCase("CSNOFinderService")) {
				alreadyRunning = true;
				System.out.println("Running");
				break;
			}
		}
		return alreadyRunning;
	}

    /**
     * Returns path to system.properties ,csnoserv/ or csnofinder/ based on parameter
     * @param uri boolean value,if true will return path to system.properties,else,till csnoserv/ or csnofinder/
     */
    private String getURIFromPropertiesFileGeneric(boolean uri) {
        String confPath = "";
        try {
            File jarFile = new File(
                    SNOMEDAgent.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
            if(uri)
                confPath = jarFile.getParentFile().getParentFile().getParentFile().getPath() + File.separator + "system.properties";
            else
                confPath = jarFile.getParentFile().getParentFile().getParentFile().getParentFile().getPath() + File.separator;
        } catch (URISyntaxException exp) {
            System.out.println(exp.getMessage());
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return confPath;
    }

	public void launch() {
		// Create a basic jetty server object that will listen on the provided port or
		// else default port 8080.
		// Note that if you set this to port 0 then a randomly available port
		// will be assigned that you can either look in the logs for the port,
		// or programmatically obtain it for use in test cases.

		// Setup JMX
		MBeanContainer mbContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
		server.addBean(mbContainer);
		server.setStopAtShutdown(true);
		// The WebAppContext is the entity that controls the environment in
		// which a web application lives and breathes.

		WebAppContext webappServ = new WebAppContext();

		webappServ.setContextPath("/csnoserv");
		webappServ.setPersistTempDirectory(false);

		File warFileServ = new File( getURIFromPropertiesFileGeneric(false) + "csnoserv");
		webappServ.setWar(warFileServ.getAbsolutePath());
		webappServ.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");

		// A WebAppContext is a ContextHandler as well so it needs to be set to
		// the server so it is aware of where to send the appropriate requests.
		// server.setHandler(webapp);

		WebAppContext webappFinder = new WebAppContext();
		webappFinder.setContextPath("/csnofinder");
		webappFinder.setPersistTempDirectory(false);
		// File warFileFinder = new File("WebContentFinder");
		File warFileFinder = new File( getURIFromPropertiesFileGeneric(false) + "csnofinder");
		webappFinder.setWar(warFileFinder.getAbsolutePath());
		webappFinder.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false");

		// A WebAppContext is a ContextHandler as well so it needs to be set to
		// the server so it is aware of where to send the appropriate requests.
		// server.setHandler(webappFinder);

		ContextHandlerCollection contexts = new ContextHandlerCollection();
		contexts.setHandlers(new Handler[] { webappServ, webappFinder });

		server.setHandler(contexts);
		try {
			// Start things up!
			server.start();

			server.dumpStdErr();
			// The use of server.join() will make the current thread join and
			// wait until the server is done executing.
			server.join();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void run() {
		Launcher launchObj = new Launcher();
		launchObj.launch();

	}
}
