/**
 * (c) 2013 JOJO
 * Eclipse Public License
 */
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

/**
 * @auter JOJO
 */
public class jard
{
	static final int BUFFER_SIZE = 10240;
	
	static String usage = "Usage: jard [--delete][-vf] [archive file] files ...\n"
			+ "  --delete: Delete files from archive\n"
			+ "  -v: verbosely list files processed\n"
			+ "  -f: archive file\n";
	static boolean verbose = false;
	
	public static void main(String[] args) throws Exception {
		String jarName = null;
		final ArrayList<PathMatcher> fileGlobs = new ArrayList<>();
		
		final int argc = args.length;
		int argx = 0;
		
		String cmd;
		while (argx < argc && (cmd = args[argx++]).startsWith("-")) {
			if (cmd.equals("--delete"))
				/*ignore*/;
			else {
				for (int i = 1; i < cmd.length(); ++i) {
					switch (cmd.charAt(i)) {
					case 'v':
						verbose = true;
						break;
					case 'f':
						if (argx < argc)
							jarName = args[argx++];
						else
						{
							System.err.println("ERROR: Unknown archive file.");
							System.err.println(usage);
							System.exit(1);
						}
						break;
					default:
						System.err.println("ERROR: Unknown command '" + cmd + "'");
						System.err.println(usage);
						System.exit(1);
					}
				}
				break;
			}
		}
		
		final FileSystem fileSystems = FileSystems.getDefault();
		while (argx < argc)
			fileGlobs.add(fileSystems.getPathMatcher("glob:" + args[argx++]));
		
		if (jarName == null) {
			System.err.println("ERROR: Unknown archive file.");
			System.err.println(usage);
			System.exit(1);
		}
		if (fileGlobs.size() == 0) {
			System.err.println("ERROR: Unknown files.");
			System.err.println(usage);
			System.exit(1);
		}
		
		int update = 0;
		ByteArrayOutputStream jarByte = new ByteArrayOutputStream();
		byte[] buffer = new byte[BUFFER_SIZE];
		
		try (JarFile jarFile = new JarFile(jarName);
		     JarOutputStream out = new JarOutputStream(jarByte)) {
			FOR_ENTRY:
			for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
				JarEntry entry = entries.nextElement();
				if (entry == null)
					break;
				final Path path = Paths.get(entry.getName());
				for (PathMatcher glob : fileGlobs) {
					if (glob.matches(path)) {
						if (verbose)
							System.out.println("deleting: " + entry.getName());
						++update;
						continue FOR_ENTRY;
					}
				}
				
				if (entry.isDirectory()) {
				//	out.putNextEntry(entry);
				//	out.closeEntry();
				} else {
					try (InputStream in = jarFile.getInputStream(entry)) {
						out.putNextEntry(entry);
						for (int nRead; (nRead = in.read(buffer)) >= 0;)
							out.write(buffer, 0, nRead);
					}
					out.closeEntry();
				}
			}
		}
		
		if (update > 0) {
			try (FileOutputStream os = new FileOutputStream(jarName)) {
				os.write(jarByte.toByteArray());
			}
			if (verbose)
				System.out.println(update + " files deleted.");
		}
	}
}