package net.oni2.aeinstaller.updater.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

import net.oni2.aeinstaller.updater.backend.Paths;
import net.oni2.platformtools.applicationinvoker.ApplicationInvoker;
import net.oni2.platformtools.applicationinvoker.EExeType;
import net.oni2.platformtools.applicationinvoker.ERuntimeNotInstalledException;
import net.oni2.svnaccess.SVN;
import net.oni2.svnaccess.SVNUpdateListener;

/**
 * @author Christian Illy
 */
public class MainWin extends JFrame {
	private static final long serialVersionUID = -3653187495409881426L;

	JLabel step = new JLabel("Preparing");
	JProgressBar bar = new JProgressBar(0, 1);
	JButton closeBtn = new JButton("Close and launch AEI");

	/**
	 * Constructor of main window.
	 */
	public MainWin() {
		super("AEInstaller2 self updater");
		setLayout(new BorderLayout(2, 4));

		bar.setPreferredSize(new Dimension(250, 16));
		closeBtn.setEnabled(false);

		add(bar, BorderLayout.CENTER);
		add(step, BorderLayout.NORTH);
		add(closeBtn, BorderLayout.SOUTH);

		setResizable(false);
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		pack();
		setLocationRelativeTo(null);

		closeBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				exit();
			}
		});

		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				super.windowClosing(e);
				if (closeBtn.isEnabled()) {
					exit();
				}
			}
		});

		Updater upd = new Updater();
		upd.execute();
	}

	private void exit() {
		File aei = new File(new File(Paths.getInstallerPath(), "bin"),
				"AEInstaller2.jar");
		if (aei.exists()) {
			try {
				ApplicationInvoker
						.execute(EExeType.JAR, null, aei, null, false);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ERuntimeNotInstalledException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		dispose();
	}

	class Status {
		public Status(int done, int total) {
			this.done = done;
			this.total = total;
		}

		/**
		 * Steps done
		 */
		public int done;
		/**
		 * Steps in total to do
		 */
		public int total;
	}

	class Updater extends SwingWorker<Status, Status> {
		boolean uptodate = false;

		@Override
		protected Status doInBackground() throws Exception {
			step.setText("Waiting for AEI to close");
			int i = 0;
			while (!checkWritable() && i < 20) {
				i++;
				Thread.sleep(500);
			}

			if (i >= 20) {
				JOptionPane
						.showMessageDialog(
								null,
								"Could not update because the main file of AEI was locked.\nPerhaps you are still running an instance of AEI?",
								"Could not update!", JOptionPane.ERROR_MESSAGE);
				System.exit(1);
				return null;
			}

			step.setText("Updating");

			SVN svn = new SVN();
			try {
				int x = svn.checkSVN("http://svn.aei.oni2.net",
						new File(Paths.getPrefsPath(), "bin"));
				switch (x) {
					case -2: // No repos connection
						break;
					case 0: // Repos up to date
						uptodate = true;
						break;
					case -1:// no WC yet
					case 1:// Update available
					case 2:// missing files
						uptodate = svn.updateWC("http://svn.aei.oni2.net",
								new File(Paths.getPrefsPath(), "bin"),
								new SVNUpdateListener() {
									public void statusUpdate(int done, int total) {
										publish(new Status(done, total));
									}
								});
						break;
				}
				if (!uptodate) {
					JOptionPane
							.showMessageDialog(
									null,
									"Perhaps you don't have a internet connection right now or\nyou have (not) entered (wrong) proxy data?",
									"Updating AEI failed!",
									JOptionPane.ERROR_MESSAGE);
					System.exit(1);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		}

		private boolean checkWritable() {
			File aei = new File(new File(Paths.getInstallerPath(), "bin"),
					"AEInstaller2.jar");
			File temp = new File(new File(Paths.getInstallerPath(), "bin"),
					"temp.jar");
			if (!aei.exists())
				return true;
			if (aei.renameTo(temp)) {
				temp.renameTo(aei);
				return true;
			}
			return false;
		}

		@Override
		protected void process(List<Status> chunks) {
			super.process(chunks);
			if (chunks.size() > 0) {
				Status s = chunks.get(chunks.size() - 1);
				bar.setValue(s.done);
				bar.setMaximum(s.total);
			}
		}

		@Override
		protected void done() {
			super.done();
			if (uptodate) {
				step.setText("AEI is up to date");
				bar.setValue(1);
				bar.setMaximum(1);
				closeBtn.setEnabled(true);
			}
		}
	}

}
