/*
 * 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();
	}
}
