/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package flash.tools.debugger;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import flash.util.Trace;

/**
 * @author mmorearty
 */
public class DefaultDebuggerCallbacks implements IDebuggerCallbacks
{
	private boolean m_computedExeLocations;
	private File m_httpExe;
	private File m_playerExe;

	private static final String UNIX_DEFAULT_BROWSER = "firefox"; //$NON-NLS-1$
	private static final String UNIX_FLASH_PLAYER = "flashplayer"; //$NON-NLS-1$

	private static final int WINDOWS = 0;
	private static final int MAC = 1;
	private static final int UNIX = 2;

	// A pattern for a value that was output by reg.exe.  Warning,
	// Windows XP and Windows Vista have different output; the following
	// pattern needs to work for both.
	private static final Pattern registryValuePattern = Pattern.compile("\\sREG_[^ \t]+\\s+(.*)$"); //$NON-NLS-1$

	/**
	 * Returns WINDOWS, MAC, or UNIX
	 */
	private static int getOS() {
		String osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$
		if (osName.startsWith("windows")) //$NON-NLS-1$
			return WINDOWS;
		else if (osName.startsWith("mac os x")) // as per http://developer.apple.com/technotes/tn2002/tn2110.html //$NON-NLS-1$
			return MAC;
		else
			return UNIX;
	}

	/*
	 * @see flash.tools.debugger.IDebuggerCallbacks#getHttpExe()
	 */
	public synchronized File getHttpExe()
	{
		if (!m_computedExeLocations)
			recomputeExeLocations();
		return m_httpExe;
	}

	/*
	 * @see flash.tools.debugger.IDebuggerCallbacks#getPlayerExe()
	 */
	public synchronized File getPlayerExe()
	{
		if (!m_computedExeLocations)
			recomputeExeLocations();
		return m_playerExe;
	}

	/*
	 * @see flash.tools.debugger.IDebuggerCallbacks#recomputeExeLocations()
	 */
	public synchronized void recomputeExeLocations()
	{
		int os = getOS();
		if (os == WINDOWS)
		{
			m_httpExe = getDefaultWindowsBrowser();
			m_playerExe = determineExeForType("ShockwaveFlash.ShockwaveFlash"); //$NON-NLS-1$
		}
		else if (os == MAC)
		{
			m_httpExe = null;
			m_playerExe = null;
		}
		else // probably Unix
		{
			// "firefox" is default browser for unix
			m_httpExe = findUnixProgram(UNIX_DEFAULT_BROWSER);

			// "flashplayer" is standalone flash player on unix
			m_playerExe = findUnixProgram(UNIX_FLASH_PLAYER);
		}
		m_computedExeLocations = true;
	}

	public String getHttpExeName()
	{
		if (getOS() == UNIX)
			return UNIX_DEFAULT_BROWSER;
		else
			return Bootstrap.getLocalizationManager().getLocalizedTextString("webBrowserGenericName"); //$NON-NLS-1$
	}

	public String getPlayerExeName()
	{
		if (getOS() == UNIX)
			return UNIX_FLASH_PLAYER;
		else
			return Bootstrap.getLocalizationManager().getLocalizedTextString("flashPlayerGenericName"); //$NON-NLS-1$
	}

	/**
	 * Looks for a Unix program.  Checks the PATH, and if not found there,
	 * checks the directory specified by the "application.home" Java property.
	 * ("application.home" was set by the "fdb" shell script.)
	 * 
	 * @param program program to find, e.g. "firefox"
	 * @return path, or <code>null</code> if not found.
	 */
	private File findUnixProgram(String program)
	{
		String[] cmd = { "/bin/sh", "-c", "which " + program }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		try
		{
			Process process = Runtime.getRuntime().exec(cmd);
			BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
			String line = reader.readLine();
			if (line != null)
			{
				File f = new File(line);
				if (f.exists())
				{
					return f;
				}
			}

			// Check in the Flex SDK's "bin" directory.  The "application.home"
			// property is set by the "fdb" shell script.
			String flexHome = System.getProperty("application.home"); //$NON-NLS-1$
			if (flexHome != null)
			{
				File f = new File(flexHome, "bin/" + program); //$NON-NLS-1$
				if (f.exists())
				{
					return f;
				}
			}
		}
		catch (IOException e)
		{
			// ignore
		}
		return null;
	}

	private File getDefaultWindowsBrowser() {
		try {
			String browser = null;

			double osVersion;
			try {
				osVersion = Double.parseDouble(System.getProperty("os.version")); //$NON-NLS-1$
			} catch (NumberFormatException e) {
				osVersion = 0;
			}

			if (osVersion >= 6) { // Vista or higher
				String progid = queryWindowsRegistry(
					"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice", //$NON-NLS-1$
					"Progid"); //$NON-NLS-1$
				if (progid != null) {
					browser = getClassShellOpenCommand(progid);
				}
			}

			if (browser == null) {
				browser = getClassShellOpenCommand("http"); //$NON-NLS-1$
			}

			if (browser != null) {
				browser = extractExenameFromCommandString(browser);
				return new File(browser);
			} else {
				return null;
			}
		} catch (IOException e) {
			return null;
		}
	}

	private String getClassShellOpenCommand(String clazz) throws IOException {
		return queryWindowsRegistry("HKEY_CLASSES_ROOT\\" + clazz + "\\shell\\open\\command", null); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Note, this function is Windows-specific.
	 */
	private File determineExeForType(String type)
	{
		String it = null;
		try
		{
			String[] cmd = new String[] { "cmd", "/d", "/c", "ftype", type }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
			Process p = Runtime.getRuntime().exec(cmd);
			LineNumberReader lnr = new LineNumberReader(new InputStreamReader(p.getInputStream()));
			String line = null;
			type += "="; //$NON-NLS-1$
			while( it == null && (line = lnr.readLine()) != null)
			{
				if (line.length() < type.length() ||
					line.substring(0, type.length()).compareToIgnoreCase(type) == 0)
				{
					it = line;
					break;
				}
			}
			p.destroy();

			// if we have one extract cmd = " "
			if (it != null)
			{
				int equalSign = it.indexOf('=');
				if (equalSign != -1)
					it = it.substring(equalSign+1);

				it = extractExenameFromCommandString(it);
			}
		}
		catch (IOException e)
		{
			// means it didn't work
		}

		if (it != null)
			return new File(it);
		else
			return null;
	}

	/**
	 * Given a command string of the form
	 * 		"path_to_exe" args
	 * or
	 * 		path_to_exe args
	 * 
	 * return the path_to_exe.  Note that path_to_exe may contain spaces.
	 */
	protected String extractExenameFromCommandString(String cmd)
	{
		// now strip trailing junk if any
		if (cmd.startsWith("\"")) { //$NON-NLS-1$
			// ftype is enclosed in quotes
			int closingQuote =  cmd.indexOf('"', 1);
			if (closingQuote == -1)
				closingQuote = cmd.length();
			cmd = cmd.substring(1, closingQuote);
		} else {
			// Some ftypes don't use enclosing quotes.  This is tricky -- we have to
			// scan through the string, stopping at each space and checking whether
			// the filename up to that point refers to a valid filename.  For example,
			// if the input string is
			//
			//     C:\Program Files\Macromedia\Flash 9\Players\SAFlashPlayer.exe %1
			//
			// then we need to stop at each space and see if that is an EXE name:
			//
			//     C:\Program.exe
			//     C:\Program Files\Macromedia\Flash.exe
			//     C:\Program Files\Macromedia\Flash 9\Players\SAFlashPlayer.exe

			int endOfFilename = -1;
			for (;;) {
				int nextSpace = cmd.indexOf(' ', endOfFilename+1);
				if (nextSpace == -1) {
					endOfFilename = -1;
					break;
				}
				String filename = cmd.substring(0, nextSpace);
				if (!filename.toLowerCase().endsWith(".exe")) //$NON-NLS-1$
					filename += ".exe"; //$NON-NLS-1$
				if (new File(filename).exists()) {
					endOfFilename = nextSpace;
					break;
				}
				endOfFilename = nextSpace;
			}
			if (endOfFilename != -1 && endOfFilename < cmd.length())
				cmd = cmd.substring(0, endOfFilename);
		}
		return cmd;
	}

	/*
	 * @see flash.tools.debugger.IDebuggerCallbacks#launchDebugTarget(java.lang.String[])
	 */
	public Process launchDebugTarget(String[] cmd) throws IOException
	{
		return Runtime.getRuntime().exec(cmd);
	}
	
	@Override
	public Process launchDebugTarget(String[] cmd, ILauncher launcher) throws IOException {
		return launcher.launch(cmd);
	}
	
	/*
	 * @see flash.tools.debugger.IDebuggerCallbacks#terminateDebugTarget(java.lang.Process)
	 */
	public void terminateDebugTarget(Process process) throws IOException
	{
		terminateDebugTarget(process, null);
	}
	
	@Override
	public void terminateDebugTarget(Process process, ILauncher launcher) throws IOException {
		if(null == launcher)
		{
			process.destroy();
		}
		else
		{
			launcher.terminate(process);
		}
		
	}
	
	public String queryWindowsRegistry(String key, String value) throws IOException
	{
		return queryWindowsRegistry(key, value, 0);
	}

	/**
	 * This implementation of queryWindowsRegistry() does not make any native
	 * calls.  I had to do it this way because it is too hard, at this point,
	 * to add native code to the Flex code tree.
	 */
	public String queryWindowsRegistry(String key, String value, int registryBitMode) throws IOException
	{
		Process p = null;
		String result = null;

		List<String> arguments = new ArrayList<String>(6);
		arguments.add("reg.exe"); //$NON-NLS-1$
		arguments.add("query"); //$NON-NLS-1$
		arguments.add(key);
		if (value == null || value.length() == 0)
		{
			arguments.add("/ve"); //$NON-NLS-1$
		}
		else
		{
			arguments.add("/v"); //$NON-NLS-1$
			arguments.add(value);
		}

		// This line must not be in try/catch -- if it throws an exception,
		// we want that to propagate out to our caller.
		p = Runtime.getRuntime().exec(arguments.toArray(new String[arguments.size()]));

		try
		{
			BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

			String line;
			while ((line = reader.readLine()) != null)
			{
				if (line.equalsIgnoreCase(key))
				{
					line = reader.readLine();
					if (line != null)
					{
						Matcher matcher = registryValuePattern.matcher(line);
						if (matcher.find()) {
							result = matcher.group(1);
						}
					}
					break;
				}
			}
		}
		catch (IOException e)
		{
			if (Trace.error)
				e.printStackTrace();
		}
		finally
		{
			if (p != null)
			{
				p.destroy();
				p = null;
			}
		}

		return result;
	}

	/**
	 * Default implementation does not know how to get the version
	 * of an application.
	 */
	public int[] getAppVersion(File application) throws IOException {
		return null;
	}
	
	/**
	 * Default application does not have any extra arguments for the
	 * browser.
	 */
	public String[] getBrowserParameters(String uri)
	{
		return null;
	}
}
