/*
 * @(#)CDcreator.java
 *
 * This file is part of webCDwriter - Network CD Writing.
 *
 * Copyright (C) 1999-2003 Jörg P. M. Haeger
 *
 * webCDwriter 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.
 *
 * webCDwriter 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 webCDwriter; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Jörg Haeger, 14.05.1999
 */

import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import netscape.security.PrivilegeManager;

/**
 * The main class of webCDcreator.
 *
 * @version 20030306
 * @author Jörg P. M. Haeger
 */
public class CDcreator extends JApplet
	implements java.awt.event.ActionListener {
	public static String serverName = Config.serverName;
	public static int serverPortNo = Config.serverPortNo;
	public static String osName, osVersion,
		vmName, vmVersion;
	public static boolean vmUnknown = true;
	public static Socket socket;
	public static BufferedReader inStream;
	public static DataOutputStream outStream;
	public static CDcreator app = null, applet = null;
	public static MainWin mainWin = null;
	private JButton startButton;
	public static Locale locale;
	static ResourceBundle messages;
	public static int
		maxCopies = 1,
		maxSpeed = 4;
	public static boolean
		anonymousUse = false,
		audioCDSupport = false,
		cdrdao = false,
		copySupport = false,
		DVDplusRWSupport = false,
		mp3Support = false,
		oggSupport = true,
		overburnSupport = false,
		verifySupport = false;
	public static WebStart webStart;

	public void actionPerformed(java.awt.event.ActionEvent e) {
		if (e.getActionCommand().equals("quitCmd")) {
			closeConnection();
			mainWin.setVisible(false);
			mainWin = null;
			startButton.setEnabled(true);
			synchronized(this) {
				notifyAll();
			}
			return;
		}

		if (isNetscapeVM())
		try {
			PrivilegeManager.enablePrivilege(
				"UniversalPropertyRead");
			PrivilegeManager.enablePrivilege(
				"UniversalFileRead");
		}
		catch (Exception e2) {
		}

		// check the privileges
		try {
			File f = new SecFile("C:\\");
			if (!f.exists())
				f = new SecFile("/");
			f.exists();
		}
		catch (java.security.AccessControlException e1) {
			new JOptionPane(
				i18n("accessError"),
				JOptionPane.ERROR_MESSAGE,
				JOptionPane.DEFAULT_OPTION)
			.createDialog(this, i18n("titleAccessError")).show();
			return;
		}
		catch (Exception e2) {
			new JOptionPane(
				"unknown Error",
				JOptionPane.ERROR_MESSAGE,
				JOptionPane.DEFAULT_OPTION)
			.createDialog(this, "Error").show();
			return;
		}

		startButton.setEnabled(false);
		openMainWin();
	}

	void closeConnection() {
		try {
			if (socket != null) {
				socket.close();
				socket = null;
			}
		} catch (java.io.IOException e) {
			System.out.println(
				"closeConnection(): java.io.IOException");
		}
	}

	public void closeMainWin() {
		if (mainWin == null)
			return;

		try {
			if (socket != null) {
				socket.close();
				socket = null;
			}
		} catch (java.io.IOException e) {
			System.out.println(
				"closeMainWin(): java.io.IOException");
		}

		mainWin.setVisible(false);
		mainWin = null;
		if (isApplet())
			startButton.setEnabled(true);
		else
			System.exit(0);
	}

	public void destroy() {
		Version.showDebugInfo(20, "Applet.destroy() start");
		synchronized(this) {
			while (mainWin != null)
			try {
				wait();
			} catch (InterruptedException e) {
			}
		}
		Version.showDebugInfo(20, "Applet.destroy() end");
	}

	public static URL getURL(String fileName) {
		URL url;
		if (app != null) {
			url = app.getClass().getResource(fileName);
			if (url == null)
				try {
					url = new URL(
						"http", serverName, serverPortNo,
						"/webCDcreator/" + fileName);
				} catch (Exception e) {}
		}
		else
		if (applet != null) {
			url = applet.getClass().getResource(fileName);
			if (url == null)
				// required by Netscape 4.7x
				try {
					url = new URL(
						applet.getCodeBase(),
						fileName);
				} catch (java.net.MalformedURLException e) {}
		}
		else
			url = null;

		Version.debug("getURL()", fileName + " -> " + url);
		return url;
	}

	static public String i18n(String key) {
		try {
			String str = key;
			if (key.equals("optionSimulate"))
				str = "laserOff";
			String msg = messages.getString(str);
			if (msg.startsWith("-> "))
				msg = messages.getString(msg.substring(3));
			String CD = "CD", CDR = "CD-R", CDRW = "CD-RW";
			if (Mode.isMedium(Mode.DVDPLUSRW)) {
				CD = "DVD";
				CDR = CDRW = "DVD+RW";
			}
			return replaceAll(replaceAll(
				replaceAll(msg,
					"@CD-RW@", CDRW),
					"@CD-R@", CDR),
					"@CD@", CD);
		}
		catch (MissingResourceException e) {
			try {
				return messages.getString(key);
			}
			catch (MissingResourceException e2) {
				return key;
			}
		}
	}

	public void init() {
		Version.showDebugInfo(20, "Applet.init()");
		showProductInfo();
		System.out.println("applet.bounds = " + getBounds());
		applet = this;

		readProperties();

		serverName = getCodeBase().getHost();

		initMessages(getParameter("language"),
			getParameter("country"));

		if (getParameter("server") != null)
			serverName = getParameter("server");
		if (getParameter("port") != null)
			serverPortNo = new Integer(getParameter("port"))
				.intValue();

		startButton = new JButton(i18n("startCmd"));
		startButton.addActionListener(this);
		startButton.setToolTipText(i18n("TTstart"));
		getContentPane().add(startButton);
//		getContentPane().add(new MainPanel());
	}

	private static void initMessages(String language, String country) {
		if (language == null || language.length() == 0)
			language = Locale.getDefault().getLanguage();

		if (country == null)
			country = "";

		setLocale2(new Locale(language, country));

		System.out.println(
			"language = <" + language + ">"
			+ " country = <" + country + ">"
			+ " locale = <" + new Locale(language, country) + ">"
			+ " default = <" + Locale.getDefault() + ">");
	}

	public static boolean isApplet() {
		return applet != null;
	}

	public static boolean isNetscapeVM() {
		return vmName.equals("unknown"); // vmUnknown;
	}

	public static void main(String args[]) {
		showProductInfo();
		app = new CDcreator();
		app.readProperties();
		String country = null, language = null;

		// Java Web Start init
		try {
			Class.forName("javax.jnlp.ServiceManager");
			webStart = new WebStart();
			System.out.println("codeBase = " + webStart.getCodeBase());
			serverName = webStart.getCodeBase().getHost();
		} catch (Exception e) {}

		boolean error = false;
		for (int i = 0; i < args.length; i++)
			if (args[i].startsWith("server="))
				serverName = args[i].substring(7);
			else
			if (args[i].startsWith("port="))
				serverPortNo = new Integer(
					args[i].substring(5)).intValue();
			else
			if (args[i].startsWith("country="))
				country = args[i].substring(8);
			else
			if (args[i].startsWith("language="))
				language = args[i].substring(9);
			else
				error = true;

		initMessages(language, country);

		if (error) {
			System.out.println(Version.product + " "
				+ Version.version);
//			System.out.println("Author: " + Version.author);
			System.out.println("Arguments and their defaults:");
			System.out.println("country=" + locale.getCountry());
			System.out.println("language=" + locale.getLanguage());
			System.out.println("port=" + Config.serverPortNo);
			System.out.println("server=" + Config.serverName);
			System.exit(0);
		}

		app.openMainWin();
	}

	public void openMainWin() {
		mainWin = new MainWin();
		if (true || applet == null) {
			Rectangle screenRect;
			try {
				mainWin.getClass().getMethod(
					"getGraphicsConfiguration", null);
				screenRect = mainWin.getGraphicsConfiguration()
					.getBounds();
			}
			catch (NoSuchMethodException e) {
				screenRect = new Rectangle(0, 0, 1024, 768);
			}
			int width = 640, height = 480;
			mainWin.setBounds(
				screenRect.x + (screenRect.width - width) / 2,
				screenRect.y + (screenRect.height - height) / 2,
				width, height);
		}
		else {
			Point p = applet.getLocation();
			mainWin.setBounds(p.x, p.y, 640, 480);
			System.out.println(p.x + ", " + p.y);
		}
		mainWin.setVisible(true);

		State.reset();
		State.userID = System.getProperty("user.name")
			.replace(' ', '_');

		Options.reset();

		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					new Connect(serverName, serverPortNo).exec();
					if (overburnSupport)
						Mode.addMedium(Mode.CDR90);
					mainWin.createMenuBar();
					if (!anonymousUse) {
						LoginDialog login = new LoginDialog();
						mainWin.center(login);
						login.show();
						if (login.wasCanceled())
							throw new CommandError();
					}
					mainWin.typeSelection(false);
					mainWin.addServerExports();
				} catch (CommandError cmdErr) {
					closeMainWin();
				}
			}
		});
	}

	private void readProperties() {
		osName = System.getProperty("os.name").replace(' ', '_');
		osVersion = System.getProperty("os.version")
			.replace(' ', '_');

		try {
			vmName = System.getProperty("java.vm.name");
			vmVersion = System.getProperty("java.vm.version");
		}
		catch (Exception e1) {
			try {
//				PrivilegeManager.enablePrivilege(
//					"UniversalPropertyRead");
				vmName = System.getProperty("java.vm.name");
				vmVersion = System.getProperty(
					"java.vm.version");
			}
			catch (Exception e2) {
				vmName = "unknown";
				vmVersion = "unknown";
			}
		}

		if (vmName == null || vmName.equals(""))
			vmName = "unknown";
		else {
			vmName = vmName.replace(' ', '_');
			vmUnknown = false;
		}
		if (vmVersion == null || vmVersion.equals(""))
			vmVersion = "unknown";
		else
			vmVersion = vmVersion.replace(' ', '_');
	}

	static class MyBundle extends PropertyResourceBundle {
		MyBundle(InputStream in, ResourceBundle parent)
				throws IOException {
			super(in);
			setParent(parent);
		}

		public static ResourceBundle getBundle2(
			String baseName, Locale locale) {
			ResourceBundle bundle = null;
			try {
				InputStream in = getURL(baseName
					+ ".properties").openStream();
				bundle = new PropertyResourceBundle(in);
			} catch (Exception e) {
				System.out.println(e);
			}

			if (locale.getLanguage().length() == 0)
				return bundle;

			try {
				InputStream in = getURL(baseName
					+ "_" + locale.getLanguage()
					+ ".properties").openStream();
				bundle = new MyBundle(in, bundle);
			} catch (Exception e) {
				System.out.println(e);
			}

			if (locale.getCountry().length() == 0)
				return bundle;

			try {
				InputStream in = getURL(baseName
					+ "_" + locale.getLanguage()
					+ "_" + locale.getCountry()
					+ ".properties").openStream();
				bundle = new MyBundle(in, bundle);
			} catch (Exception e) {
				System.out.println(e);
			}

			return bundle;
		}
	}

	static String replaceAll(
			String str, String regex, String replacement) {
		if (str.indexOf(regex) < 0)
			return str;

		String str2 = "";
		int p0 = 0;
		while (true) {
			int p = str.indexOf(regex, p0);
			if (p < 0) {
				str2 += str.substring(p0);
				break;
			}
			str2 += str.substring(p0, p) + replacement;
			p0 = p + regex.length();
		}

		return str2;
	}

	static void setLocale2(Locale locale) {
		CDcreator.locale = locale;

		if (isNetscapeVM()) {
			messages = MyBundle.getBundle2("i18n/Messages", locale);
			return;
		}

		ClassLoader loader = new ClassLoader() {
/*			public Class findClass(String name)
					throws ClassNotFoundException {
				System.out.println("findClass: " + name);
				try {
					InputStream in = getURL(name)
						.openStream();
					byte[] bs = new byte[64 * 1024];
					int n = in.read(bs);
					return defineClass(name, bs, 0, n);
				} catch (Exception e) {
					System.out.println(e);
					throw new ClassNotFoundException();
				}
			}
*/
			public URL findResource(String name) {
				Version.debug("ClassLoader", "findResource: " + name);
				URL url = super.findResource(name);
				if (url != null)
					return url;
				return getURL(name);
			}

			public URL getResource(String name) {
				Version.debug("ClassLoader", "getResource: " + name);
				URL url = super.getResource(name);
				if (url != null)
					return url;
				return getURL(name);
			}

			public Class loadClass(String name)
				throws ClassNotFoundException {
				throw new ClassNotFoundException();
			}
		};

//		URL[] urls = { getURL("/") };
//		ClassLoader loader = new URLClassLoader(urls);
		messages = ResourceBundle.getBundle(
			"i18n/Messages", locale, loader);
	}

	public static void showDocument(String name) {
		URL url = null;
		if (applet != null) {
			try {
				url = new URL(
					applet.getCodeBase(),
					name);
			} catch (java.net.MalformedURLException e) {}
		}
		else
		if (webStart != null) {
			try {
				url = new URL(
					webStart.getCodeBase(),
					name);
			} catch (java.net.MalformedURLException e) {}
		}
		else
			url = getURL(name);

		showDocument(url);
	}

	public static void showDocument(URL url) {
		if (applet != null)
			applet.getAppletContext()
				.showDocument(url, "_blank");
		else
		if (webStart != null)
			webStart.showDocument(url);
		else
			new HelpWin(url).show();
	}

	public static void showProductInfo() {
		System.out.println(
			Version.product + " " + Version.version
				+ " " + Version.copyright);
	}

	public static void showServerDocument(String name) {
		try {
			URL url = new URL("http",
				serverName, serverPortNo, name);
			showDocument(url);
		} catch (java.net.MalformedURLException urlExp) {
		}
	}

	public void stop() {
		Version.showDebugInfo(20, "Applet.stop()");
	}

	public void start() {
		Version.showDebugInfo(20, "Applet.start()");
	}

	public static boolean useUnicodeFont() {
		return locale.getLanguage().equals("ko")
			|| locale.getLanguage().equals("zh");
	}
}
