/*
 * Copyright (c) 2005, Joe Desbonnet, (jdesbonnet@gmail.com)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */package ie.wombat.jbdiff;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPInputStream;

/**
 * Java Binary patcher (based on bspatch by Colin Percival)
 * 
 * @author Joe Desbonnet, joe@galway.net
 */
public class JBPatch {

	// JBPatch extensions by Stefan.Liebig@compeople.de:
	//
	// - uses GZIP compressor to compress ALL of the blocks (ctrl,diff,extra).
	// - added an interface that allows using of JBPatch with streams and byte
	// arrays

	private static final String VERSION = "jbdiff-0.1.0";

	/**
	 * Run JBPatch from the command line. Params: oldfile newfile patchfile.
	 * newfile will be created.
	 * 
	 * @param arg
	 * @throws IOException
	 */
	public static void main(String[] arg) throws IOException {

		if (arg.length != 3) {
			System.err
					.println("usage example: java -Xmx200m ie.wombat.jbdiff.JBPatch oldfile newfile patchfile");
		}

		File oldFile = new File(arg[0]);
		File newFile = new File(arg[1]);
		File diffFile = new File(arg[2]);

		bspatch(oldFile, newFile, diffFile);
	}

	/**
	 * @param oldFile
	 * @param newFile
	 * @param diffFile
	 * @throws IOException
	 */
	public static void bspatch(File oldFile, File newFile, File diffFile)
			throws IOException {
		InputStream oldInputStream = new BufferedInputStream(
				new FileInputStream(oldFile));
		byte[] diffBytes = new byte[(int) diffFile.length()];
		InputStream diffInputStream = new FileInputStream(diffFile);
		Util.readFromStream(diffInputStream, diffBytes, 0, diffBytes.length);

		byte[] newBytes = bspatch(oldInputStream, (int) oldFile.length(),
				diffBytes);

		OutputStream newOutputStream = new FileOutputStream(newFile);
		newOutputStream.write(newBytes);
		newOutputStream.close();
	}

	/**
	 * @param oldInputStream
	 * @param diffInputStream
	 * @return
	 */
	public static byte[] bspatch(InputStream oldInputStream, int oldsize,
			byte[] diffBytes) throws IOException {
		/*
		 * Read in old file (file to be patched) to oldBuf
		 */
		// int oldsize = (int) oldFile.length();
		// byte[] oldBuf = new byte[oldsize + 1];
		byte[] oldBuf = new byte[oldsize];
		// InputStream oldIn = new FileInputStream( oldFile );
		Util.readFromStream(oldInputStream, oldBuf, 0, oldsize);
		oldInputStream.close();
		// oldIn.close();

		return JBPatch.bspatch(oldBuf, oldsize, diffBytes);
	}

	/**
	 * @param oldBuf
	 * @param oldsize
	 * @param diffBytes
	 * @return
	 * @throws IOException
	 */
	public static byte[] bspatch(byte[] oldBuf, int oldsize, byte[] diffBytes)
			throws IOException {
		return bspatch(oldBuf, oldsize, diffBytes, diffBytes.length);
	}

	/**
	 * @param oldBuf
	 * @param oldsize
	 * @param diffBuf
	 * @param diffSize
	 * @return
	 * @throws IOException
	 */
	public static byte[] bspatch(byte[] oldBuf, int oldsize, byte[] diffBuf,
			int diffSize) throws IOException {

		DataInputStream diffIn = new DataInputStream(new ByteArrayInputStream(
				diffBuf, 0, diffSize));

		// skip headerMagic at header offset 0 (length 8 bytes)
		diffIn.skip(8);

		// ctrlBlockLen after bzip2 compression at heater offset 8 (length 8
		// bytes)
		long ctrlBlockLen = diffIn.readLong();

		// diffBlockLen after bzip2 compression at header offset 16 (length 8
		// bytes)
		long diffBlockLen = diffIn.readLong();

		// size of new file at header offset 24 (length 8 bytes)
		int newsize = (int) diffIn.readLong();

		// System.err.println( "newsize=" + newsize );
		// System.err.println( "ctrlBlockLen=" + ctrlBlockLen );
		// System.err.println( "diffBlockLen=" + diffBlockLen );
		// System.err.println( "newsize=" + newsize );

		InputStream in;
		in = new ByteArrayInputStream(diffBuf, 0, diffSize);
		in.skip(Util.HEADER_SIZE);
		DataInputStream ctrlBlockIn = new DataInputStream(new GZIPInputStream(
				in));

		in = new ByteArrayInputStream(diffBuf, 0, diffSize);
		in.skip(ctrlBlockLen + Util.HEADER_SIZE);
		InputStream diffBlockIn = new GZIPInputStream(in);

		in = new ByteArrayInputStream(diffBuf, 0, diffSize);
		in.skip(diffBlockLen + ctrlBlockLen + Util.HEADER_SIZE);
		InputStream extraBlockIn = new GZIPInputStream(in);

		// byte[] newBuf = new byte[newsize + 1];
		byte[] newBuf = new byte[newsize];

		int oldpos = 0;
		int newpos = 0;
		int[] ctrl = new int[3];
		// int nbytes;
		while (newpos < newsize) {

			for (int i = 0; i <= 2; i++) {
				// ctrl[i] = diffIn.readInt();
				ctrl[i] = ctrlBlockIn.readInt();
				// System.err.println (" ctrl[" + i + "]=" + ctrl[i]);
			}

			if (newpos + ctrl[0] > newsize) {
				throw new IOException("Corrupt patch.");
			}

			/*
			 * Read ctrl[0] bytes from diffBlock stream
			 */

			Util.readFromStream(diffBlockIn, newBuf, newpos, ctrl[0]);

			for (int i = 0; i < ctrl[0]; i++) {
				if ((oldpos + i >= 0) && (oldpos + i < oldsize)) {
					newBuf[newpos + i] += oldBuf[oldpos + i];
				}
			}

			newpos += ctrl[0];
			oldpos += ctrl[0];

			if (newpos + ctrl[1] > newsize) {
				throw new IOException("Corrupt patch.");
			}

			Util.readFromStream(extraBlockIn, newBuf, newpos, ctrl[1]);

			newpos += ctrl[1];
			oldpos += ctrl[2];
		}

		// TODO: Check if at end of ctrlIn
		// TODO: Check if at the end of diffIn
		// TODO: Check if at the end of extraIn

		// This check is not needed since the byte array has been allocated with
		// this constraint!
		// if ( newBuf.length - 1 != newsize ) {
		// throw new IOException( "Corrupt patch." );
		// }

		ctrlBlockIn.close();
		diffBlockIn.close();
		extraBlockIn.close();
		diffIn.close();

		return newBuf;
		// OutputStream out = new FileOutputStream( newFile );
		// out.write( newBuf, 0, newBuf.length - 1 );
		// out.close();
	}
}
