/*
 *
 *  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 macromedia.asc.embedding;

import macromedia.asc.util.ObjectList;

import java.io.*;
import java.util.*;
import java.lang.reflect.Method;
import java.lang.reflect.Field;

public class Shell
{
	public static void main(String[] args) throws IOException
	{
		exit = false;
		counter = 1;
		targets = new HashMap();
		processes = new HashMap();

		String s;
		BufferedReader r = new BufferedReader(new InputStreamReader(System.in));

		intro();
		prompt();
		while ((s = r.readLine()) != null)
		{
			try
			{
				process(s);
			}
			catch (Throwable t)
			{
				t.printStackTrace();
			}

			if (exit)
			{
				break;
			}
			else
			{
				prompt();
			}
		}
	}

	private static int counter;
	private static boolean exit;
	private static Map targets;
	private static Map processes;

	private static void process(String s)
	{
		if (s.startsWith("asc"))
		{
			StringTokenizer t = new StringTokenizer(s.substring("asc".length()).trim(), " ");
			String[] args = new String[t.countTokens()];
			for (int i = 0; t.hasMoreTokens(); i++)
			{
				args[i] = t.nextToken();
			}

			if (args.length == 1)
			{
				try
				{
					int id = Integer.parseInt(args[0]);
					Target target = (Target) targets.get("" + id);
					if (target == null)
					{
						System.out.println("ash: Target " + id + " not found");
					}
					else
					{
						asc(target.args, id);
					}
				}
				catch (NumberFormatException ex)
				{
					System.out.println("ash: Assigned " + counter + " as the compile target id");
					asc(args, counter++);
				}
			}
			else
			{
				System.out.println("ash: Assigned " + counter + " as the compile target id");
				asc(args, counter++);
			}
		}
		else if (s.startsWith("run"))
		{
			String id = s.substring("run".length()).trim();
			if (targets.containsKey(id))
			{
				run(id);
			}
			else
			{
				System.out.println("ash: Target " + id + " not found");
			}
		}
		else if (s.startsWith("trace"))
		{
			String mode = s.substring("trace".length()).trim();
			if ("on".equalsIgnoreCase(mode))
			{
				trace(true);
			}
			else if ("off".equalsIgnoreCase(mode))
			{
				trace(false);
			}
		}
		else if (s.equals("mm.cfg"))
		{
			mmcfg();
		}
		else if (s.startsWith("clear"))
		{
			String id = s.substring("clear".length()).trim();
			if (id.length() == 0)
			{
				HashSet<String> keys = new HashSet<String>(targets.keySet());
				for (Iterator i = keys.iterator(); i.hasNext();)
				{
					clear((String) i.next());
				}
			}
			else if (targets.containsKey(id))
			{
				clear(id);
			}
			else
			{
				System.out.println("ash: Target " + id + " not found");
			}
		}
		else if (s.startsWith("info"))
		{
			String id = s.substring("info".length()).trim();
			if (id.length() == 0)
			{
				HashSet<String> keys = new HashSet<String>(targets.keySet());
				for (Iterator i = keys.iterator(); i.hasNext();)
				{
					info((String) i.next());
				}
			}
			else if (targets.containsKey(id))
			{
				info(id);
			}
			else
			{
				System.out.println("ash: Target " + id + " not found");
			}
		}
		else if (s.startsWith("touch"))
		{
			String args = s.substring("touch".length()).trim();

			StringTokenizer stok = new StringTokenizer(args);
			while (stok.hasMoreTokens())
			{
				String f = stok.nextToken();

				if (!new File(f).canWrite())
				{
					System.out.println("touch: cannot write " + f);
				}
				else
				{
					System.out.println("touched file: " + f);
					new File(f).setLastModified(System.currentTimeMillis());
				}
			}
		}
		else if (s.equals("quit"))
		{
			Set<String> names = new HashSet<String>(targets.keySet());
			for (Iterator i = names.iterator(); i.hasNext();)
			{
				process("clear " + (String) i.next());
			}

			exit = true;
		}
		else if (s.equals("memory"))
		{
			peakMemoryUsage();
		}
		else if (s.equals("gc"))
		{
			System.gc();
		}
		else
		{
			cmdList();
		}
	}

	private static MemoryUsage getMemoryUsageInBytes()
	{
		long heapUsed = 0, nonHeapUsed = 0;

	    try
	    {
	        Class mfCls = Class.forName("java.lang.management.ManagementFactory");
	        Class mpCls = Class.forName("java.lang.management.MemoryPoolMXBean");
	        Class memCls = Class.forName("java.lang.management.MemoryUsage");
		    Class typeCls = Class.forName("java.lang.management.MemoryType");

	        Class[] emptyCls = new Class[] {};
	        Object[] emptyObj = new Object[] {};
	        Method getMemPoolMeth = mfCls.getMethod("getMemoryPoolMXBeans", emptyCls);
	        Method getPeakUsageMeth = mpCls.getMethod("getPeakUsage", emptyCls);
		    Method getTypeMeth = mpCls.getMethod("getType", emptyCls);
		    Field heapField = typeCls.getField("HEAP");
		    Method resetPeakUsageMeth = mpCls.getMethod("resetPeakUsage", emptyCls);
	        Method getUsedMeth = memCls.getMethod("getUsed", emptyCls);

	        List list = (List)getMemPoolMeth.invoke(null, emptyObj);
	        for (Iterator iterator = list.iterator(); iterator.hasNext();)
	        {
	            Object memPoolObj = iterator.next();
	            Object memUsageObj = getPeakUsageMeth.invoke(memPoolObj, emptyObj);
		        Object memTypeObj = getTypeMeth.invoke(memPoolObj, emptyObj);
		        Long used = (Long)getUsedMeth.invoke(memUsageObj, emptyObj);
		        if (heapField.get(typeCls) == memTypeObj)
		        {
		            heapUsed += used.longValue();
		        }
		        else
		        {
			        nonHeapUsed += used.longValue();
		        }
		        resetPeakUsageMeth.invoke(memPoolObj, emptyObj);
	        }

		    return new MemoryUsage(heapUsed, nonHeapUsed);
	    }
	    catch(Exception e)
	    {
	        // ignore, assume not using jdk 1.5
	    }

		return new MemoryUsage(heapUsed, nonHeapUsed);
	}

	public static class MemoryUsage
	{
		public MemoryUsage(long heap, long nonHeap)
		{
			super();
			this.heap = heap;
			this.nonHeap = nonHeap;
			this.total = heap + nonHeap;
		}

		public long heap, nonHeap, total;

		public void add(MemoryUsage mem)
		{
			this.heap += mem.heap;
			this.nonHeap += mem.nonHeap;
			this.total += mem.total;
		}

		public void subtract(MemoryUsage mem)
		{
			this.heap -= mem.heap;
			this.nonHeap -= mem.nonHeap;
			this.total -= mem.total;
		}

		public String toString()
		{
			return "Peak Memory Usage: " + total + " Mb (Heap: " + heap + " Mb, Non-Heap: " + nonHeap + " Mb)";
		}
	}

	public static long peakMemoryUsage()
	{
	    return peakMemoryUsage(true);
	}

	public static long peakMemoryUsage(boolean display)
	{
		MemoryUsage mem = getMemoryUsageInBytes();
		long mbHeapUsed = (mem.heap / 1048576);
		long mbNonHeapUsed = (mem.nonHeap / 1048576);

		if (display && mem.heap != 0 && mem.nonHeap != 0)
		{
			System.out.println(new MemoryUsage(mbHeapUsed, mbNonHeapUsed));
		}

		return mbHeapUsed + mbNonHeapUsed;
	}

	private static void clear(String target)
	{
		Process p = (Process) processes.remove(target);

		if (p != null)
		{
			p.destroy();
		}

		Target s = (Target) targets.remove(target);
	}

	private static void info(String target)
	{
		Target s = (Target) targets.get(target);
		System.out.println("id: " + s.id);
		StringBuilder b = new StringBuilder();
		for (int i = 0, size = s.args.length; i < size; i++)
		{
			b.append(s.args[i]);
			b.append(' ');
		}
		System.out.println("asc: " + b);
	}

	private static void run(String target)
	{
		Process p = (Process) processes.get(target);
		Target t = (Target) targets.get(target);

		List l = new ArrayList();
		for (int i = 0; i < t.args.length; i++)
		{
			String arg = t.args[i];
			if (!arg.startsWith("-") && !arg.equalsIgnoreCase("global.abc") &&
				(arg.endsWith(".as") || arg.endsWith(".abc")))
			{
				if (arg.endsWith(".as"))
				{
					arg = arg.substring(0, arg.length() - 3) + ".abc";
				}

				l.add(arg);
			}
		}

		String[] cmdArray = new String[l.size() + 1];

		BufferedInputStream stdout = null;
		BufferedInputStream stderr = null;

		try
		{
			File player = new File(new File(System.getProperty("application.home"), "bin"), "avmplus.exe");
			if (p != null)
			{
				p.destroy();
			}
			cmdArray[0] = player.getAbsolutePath();
			for (int j = 0; j < l.size(); j++)
			{
				cmdArray[j + 1] = (String) l.get(j);
			}

			System.out.print("Using ");
			for (int j = 0; j < cmdArray.length; j++)
			{
				System.out.print(cmdArray[j] + " ");
			}
			System.out.println();

			p = Runtime.getRuntime().exec(cmdArray);
			processes.put(target, p);

			stdout = new BufferedInputStream(p.getInputStream());
			stderr = new BufferedInputStream(p.getErrorStream());

			streamOutput(stdout, System.out);
			streamOutput(stdout, System.err);

			p.waitFor();
		}
		catch (Throwable ex)
		{
			if (p != null)
			{
				p.destroy();
			}
			if (stdout != null)
			{
				try { stdout.close(); } catch (Exception e1) {}
			}
			if (stderr != null)
			{
				try { stderr.close(); } catch (Exception e2) {}
			}
			System.err.println(ex.getMessage());
			ex.printStackTrace();
		}
	}

	public static void streamOutput(InputStream in, OutputStream out)
	        throws IOException
	{
	    int len = 8192;
	    byte[] bytes = new byte[len];
	    while ((len = in.read(bytes, 0, len)) != -1)
	    {
	        out.write(bytes, 0, len);
	    }
	    out.flush();
	}

	private static void asc(String[] args, int id)
	{
		Target s = new Target();
		s.id = id;
		s.args = args;
		targets.put("" + id, s);

		try
		{
			macromedia.asc.embedding.Main.show_parsetrees = false;
			macromedia.asc.embedding.Main.show_instructions = false;
			macromedia.asc.embedding.Main.show_linenums = false;
			macromedia.asc.embedding.Main.show_bytes = false;
			macromedia.asc.embedding.Main.show_machinecode = false;
			macromedia.asc.embedding.Main.show_flow = false;
			macromedia.asc.embedding.Main.emit_debug_info = false;
			macromedia.asc.embedding.Main.emit_doc_info = false;
			macromedia.asc.embedding.Main.do_test = false;
			macromedia.asc.embedding.Main.do_help = false;
			macromedia.asc.embedding.Main.filespecFound = false; // only default param
			macromedia.asc.embedding.Main.make_movieclip = false;
			macromedia.asc.embedding.Main.lint_mode = false;
			macromedia.asc.embedding.Main.use_static_semantics = false;
			macromedia.asc.embedding.Main.sanity_mode = false;

			macromedia.asc.embedding.Main.emit_metadata = false;
			macromedia.asc.embedding.Main.log = false;
			// C: don't enable this line...
			// macromedia.asc.embedding.Main.stderr = System.err;

			macromedia.asc.embedding.Main.earliest_dialect = 7;
			macromedia.asc.embedding.Main.latest_dialect = 10;
			macromedia.asc.embedding.Main.default_dialect = 9;
			macromedia.asc.embedding.Main.dialect = macromedia.asc.embedding.Main.default_dialect;

		    macromedia.asc.embedding.Main.optimize = false;
		    macromedia.asc.embedding.Main.optimizer_configs = null;

            macromedia.asc.embedding.Main.include_filespecs = new ObjectList<String>();
			macromedia.asc.embedding.Main.import_filespecs = new ObjectList<String>();
			macromedia.asc.embedding.Main.use_namespaces = new ObjectList<String>();
			macromedia.asc.embedding.Main.swf_options = "";
			macromedia.asc.embedding.Main.language = "EN";

			macromedia.asc.embedding.Main.main(args);
			System.setErr(macromedia.asc.embedding.Main.stderr);
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
	}

	private static void trace(boolean on)
	{
		modifyPlayerConfiguration("TraceOutputFileEnable=", on);
	}

	public static String readFile(File f)
	{
		BufferedReader file = null;
		StringBuilder buffer = new StringBuilder((int) f.length());
		String lineSep = System.getProperty("line.separator");

		try
		{
			file = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
			String s = null;
			while ((s = file.readLine()) != null)
			{
				buffer.append(s);
				buffer.append(lineSep);
			}
			return buffer.toString();
		}
		catch (FileNotFoundException ex)
		{
			return null;
		}
		catch (IOException ex)
		{
			return null;
		}
		finally
		{
			if (file != null)
			{
				try
				{
					file.close();
				}
				catch (IOException ex)
				{
				}
			}
		}
	}

	public static void writeFile(String fileName, String output) throws FileNotFoundException, IOException
	{
		File file = new File(fileName);
		if (file == null)
		{
			throw new FileNotFoundException(fileName);
		}

		Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF8"));
		try
		{
			out.write(output);
			out.flush();
		}
		finally
		{
			out.close();
		}
	}

	private static void modifyPlayerConfiguration(String key, boolean on)
	{
		File parent = new File(System.getProperty("user.home"));

		File f = new File(parent, "mm.cfg");
		if (f != null && f.exists())
		{
			String mmcfg = readFile(f);
			int index = mmcfg.indexOf(key);
			if (index != -1)
			{
				mmcfg = mmcfg.substring(0, index + key.length()) + (on ? "1" : "0") + mmcfg.substring(index + key.length() + 1);
				try
				{
					writeFile(f.getAbsolutePath(), mmcfg);
				}
				catch (IOException ex)
				{
					ex.printStackTrace();
				}
				mmcfg();
			}
		}
	}

	private static void mmcfg()
	{
		File parent = new File(System.getProperty("user.home"));
		System.out.println("ash: Trying to open mm.cfg in " + parent);

		File f = new File(parent, "mm.cfg");
		if (f != null && f.exists())
		{
			System.out.println(readFile(f).trim());
		}
	}

	private static void intro()
	{
		System.out.println("Actionscript compiler SHell (ash)");
		System.out.println("Copyright 2016 The Apache Software Foundation");
		System.out.println("");
	}

	private static void prompt()
	{
		System.out.print("(ash) ");
	}

	private static void cmdList()
	{
		System.out.println("List of ash commands:");
		System.out.println("asc arg1 arg2 ...        compile; return a target id");
		System.out.println("run id                   run avmplus");
		System.out.println("clear [id]               clear target(s)");
		System.out.println("info [id]                display compile target info");
		System.out.println("gc                       run garbage collection");
		System.out.println("memory                   display current memory usage");
		System.out.println("mm.cfg                   display mm.cfg information");
		System.out.println("trace on|off             set tracing in mm.cfg");
        System.out.println("touch file1 file2...     modifies file timestamp");
		System.out.println("quit                     quit");
	}

	static class Target
	{
		public int id;
		public String[] args;
	}
}


