/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.macbundler;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.core.runtime.IProgressMonitor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;


public class BundleBuilder implements BundleAttributes {
	
	private List<Process> fProcesses= new ArrayList<Process>();
	private BundleDescription fBundleDescription;
	
	
	/**
	 * Create a new bundle
	 * @param bd the new description
	 * @param pm progress monitor
	 * @throws IOException if something happens
	 */
	public void createBundle(BundleDescription bd, IProgressMonitor pm) throws IOException {
		
		fBundleDescription= bd;
		
		File tmp_dir= new File(bd.get(DESTINATIONDIRECTORY));
		String app_dir_name= bd.get(APPNAME) + ".app";	//$NON-NLS-1$
		File app_dir= new File(tmp_dir, app_dir_name);
		if (app_dir.exists()) {
			deleteDir(app_dir);
		}
		app_dir= createDir(tmp_dir, app_dir_name, false);
		
		File contents_dir= createDir(app_dir, "Contents", false);	//$NON-NLS-1$
		createPkgInfo(contents_dir);

		File macos_dir= createDir(contents_dir, "MacOS", false);	//$NON-NLS-1$
		String launcher_path= bd.get(LAUNCHER);
		if (launcher_path == null) {
			throw new IOException();
		}		
		String launcher= copyFile(macos_dir, launcher_path, null);
		
		File resources_dir= createDir(contents_dir, "Resources", false);	//$NON-NLS-1$
		File java_dir= createDir(resources_dir, "Java", false);	//$NON-NLS-1$
				
		createInfoPList(contents_dir, resources_dir, java_dir, launcher);
		
		Iterator<Process> iter= fProcesses.iterator();
		while (iter.hasNext()) {
			Process p= iter.next();
			try {
				p.waitFor();
			} catch (InterruptedException e) {
				// silently ignore
			}
		}		
	}
	
	private void createInfoPList(File contents_dir, File resources_dir, File java_dir, String launcher) throws IOException {
		DocumentBuilder docBuilder= null;
		DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
		factory.setValidating(false);
		try {   	
			docBuilder= factory.newDocumentBuilder();
		} catch (ParserConfigurationException ex) {
			System.err.println("createInfoPList: could not get XML builder"); //$NON-NLS-1$
			throw new IOException("Could not get XML builder"); //$NON-NLS-1$
		}
		Document doc= docBuilder.newDocument();
		
		Element plist= doc.createElement("plist"); //$NON-NLS-1$
		doc.appendChild(plist);
		plist.setAttribute("version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
		
		Element dict= doc.createElement("dict"); //$NON-NLS-1$
		plist.appendChild(dict);
		
		pair(dict, "CFBundleExecutable", null, launcher); //$NON-NLS-1$
		pair(dict, "CFBundleGetInfoString", GETINFO, null); //$NON-NLS-1$
		pair(dict, "CFBundleInfoDictionaryVersion", null, "6.0"); //$NON-NLS-1$ //$NON-NLS-2$
		
		String iconName= null;
		String appName= fBundleDescription.get(APPNAME, null);
		if (appName != null)
		 {
			iconName= appName + ".icns"; //$NON-NLS-1$
		}
		String fname= copyFile(resources_dir, fBundleDescription.get(ICONFILE, null), iconName);
		if (fname != null)
		 {
			pair(dict, "CFBundleIconFile", null, fname); //$NON-NLS-1$
		}
		
		pair(dict, "CFBundleIdentifier", IDENTIFIER, null); //$NON-NLS-1$
		pair(dict, "CFBundleName", APPNAME, null); //$NON-NLS-1$
		pair(dict, "CFBundlePackageType", null, "APPL"); //$NON-NLS-1$ //$NON-NLS-2$
		pair(dict, "CFBundleShortVersionString", VERSION, null); //$NON-NLS-1$
		pair(dict, "CFBundleSignature", SIGNATURE, "????"); //$NON-NLS-1$ //$NON-NLS-2$
		pair(dict, "CFBundleVersion", null, "1.0.1"); //$NON-NLS-1$ //$NON-NLS-2$
		
		Element jdict= doc.createElement("dict"); //$NON-NLS-1$
		add(dict, "Java", jdict); //$NON-NLS-1$
		
		pair(jdict, "JVMVersion", JVMVERSION, null); //$NON-NLS-1$
		pair(jdict, "MainClass", MAINCLASS, null); //$NON-NLS-1$
		pair(jdict, "WorkingDirectory", WORKINGDIR, null); //$NON-NLS-1$
		
		if (fBundleDescription.get(USES_SWT, false))
		 {
			addTrue(jdict, "StartOnMainThread"); //$NON-NLS-1$
		}
		
		String arguments= fBundleDescription.get(ARGUMENTS, null);
		if (arguments != null) {
			Element argArray= doc.createElement("array");	//$NON-NLS-1$
			add(jdict, "Arguments", argArray);	//$NON-NLS-1$
			StringTokenizer st= new StringTokenizer(arguments);	
			while (st.hasMoreTokens()) {
				String arg= st.nextToken();
				Element type= doc.createElement("string"); //$NON-NLS-1$
				argArray.appendChild(type);	
				type.appendChild(doc.createTextNode(arg));			
			}
		}
		
		pair(jdict, "VMOptions", VMOPTIONS, null); //$NON-NLS-1$
		
		int[] id= new int[] { 0 };
		ResourceInfo[] ris= fBundleDescription.getResources(true);
		if (ris.length > 0) {
			StringBuffer cp= new StringBuffer();
			for (int i= 0; i < ris.length; i++) {
				ResourceInfo ri= ris[i];
				String e= processClasspathEntry(java_dir, ri.fPath, id);
				if (cp.length() > 0) {
					cp.append(':');
				}
				cp.append(e);
			}
			add(jdict, "ClassPath", cp.toString()); //$NON-NLS-1$
		}

		ris= fBundleDescription.getResources(false);
		if (ris.length > 0) {
			for (int i= 0; i < ris.length; i++) {
				ResourceInfo ri= ris[i];
				processClasspathEntry(java_dir, ri.fPath, id);
			}
		}

		File info= new File(contents_dir, "Info.plist"); //$NON-NLS-1$
		try (FileOutputStream fos = new FileOutputStream(info); BufferedOutputStream fOutputStream = new BufferedOutputStream(fos);) {
			// Write the document to the stream
			Transformer transformer= TransformerFactory.newInstance().newTransformer();
			transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//Apple Computer//DTD PLIST 1.0//EN"); //$NON-NLS-1$
			transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.apple.com/DTDs/PropertyList-1.0.dtd"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
			transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
			DOMSource source= new DOMSource(doc);
			StreamResult result= new StreamResult(fOutputStream);
			transformer.transform(source, result);
		} catch (TransformerException e) {
			System.err.println("createInfoPList: could not transform to XML"); //$NON-NLS-1$
		}
	}
	
	private void add(Element dict, String key, Element value) {
		Document document= dict.getOwnerDocument();
		Element k= document.createElement("key"); //$NON-NLS-1$
		dict.appendChild(k);
		k.appendChild(document.createTextNode(key));
		dict.appendChild(value);
	}
	
	private void create(Element parent, String s) {
		Document document= parent.getOwnerDocument();
		Element type= document.createElement("string"); //$NON-NLS-1$
		parent.appendChild(type);	
		type.appendChild(document.createTextNode(s));
	}

	private void createTrue(Element parent) {
		Document document= parent.getOwnerDocument();
		Element type= document.createElement("true"); //$NON-NLS-1$
		parent.appendChild(type);	
	}

	private void add(Element dict, String key, String value) {
		Document document= dict.getOwnerDocument();
		Element k= document.createElement("key"); //$NON-NLS-1$
		dict.appendChild(k);
		k.appendChild(document.createTextNode(key));
		create(dict, value);
	}
	
	private void addTrue(Element dict, String key) {
		Document document= dict.getOwnerDocument();
		Element k= document.createElement("key"); //$NON-NLS-1$
		dict.appendChild(k);
		k.appendChild(document.createTextNode(key));
		createTrue(dict);
	}
	
	private void pair(Element dict, String outkey, String inkey, String dflt) {
		String value= null;
		if (inkey != null) {
			value= fBundleDescription.get(inkey, dflt);
		} else {
			value= dflt;
		}
		if (value != null && value.trim().length() > 0) {
			add(dict, outkey, value);
		}
	}
	
	private String processClasspathEntry(File java_dir, String name, int[] id_ref) throws IOException {
		File f= new File(name);
		if (f.isDirectory()) {
			int id= id_ref[0]++;
			String archivename= "jar_" + id + ".jar"; //$NON-NLS-1$ //$NON-NLS-2$
			File to= new File(java_dir, archivename);
			zip(name, to.getAbsolutePath());
			name= archivename;
		} else {
			name= copyFile(java_dir, name, null);
		}
		return "$JAVAROOT/" + name; //$NON-NLS-1$
	}
	
	private void createPkgInfo(File contents_dir) throws IOException {
		File pkgInfo= new File(contents_dir, "PkgInfo"); //$NON-NLS-1$
		try (FileOutputStream os = new FileOutputStream(pkgInfo)) {
			os.write(("APPL" + fBundleDescription.get(SIGNATURE, "????")).getBytes()); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}
		
	private static void deleteDir(File dir) {
		File[] files= dir.listFiles();
		if (files != null) {
			for (int i= 0; i < files.length; i++) {
				deleteDir(files[i]);
			}
		}
		dir.delete();
	}
	
	private File createDir(File parent_dir, String dir_name, boolean remove) throws IOException {
		File dir= new File(parent_dir, dir_name);
		if (dir.exists()) {
			if (!remove) {
				return dir;
			}
			deleteDir(dir);
		}
		if (! dir.mkdir())
		 {
			throw new IOException("cannot create dir " + dir_name); //$NON-NLS-1$
		}
		return dir;
	}
	
	private String copyFile(File todir, String fromPath, String toname) throws IOException {
		if (toname == null) {
			int pos= fromPath.lastIndexOf('/');
			if (pos >= 0) {
				toname= fromPath.substring(pos+1);
			} else {
				toname= fromPath;
			}
		}
		File to= new File(todir, toname);
		fProcesses.add(Runtime.getRuntime().exec(new String[] { "/bin/cp", fromPath, to.getAbsolutePath() }));	//$NON-NLS-1$
		return toname;
	}

	private void zip(String dir, String dest) throws IOException {
		fProcesses.add(Runtime.getRuntime().exec(new String[] { "/usr/bin/jar", "cf", dest, "-C", dir, "." })); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
	}
}
