// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements.  See the NOTICE.txt 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 org.apache.oodt.commons.util;

import java.io.*;
import org.apache.oodt.commons.io.*;

/** Base 64 encoding and decoding.
 *
 * This class provides methods for RFC-1521 specified "base 64" encoding and decoding of
 * arbitrary data.  Pass a byte array into the {@link #encode} method and you'll get a
 * byte array result where all of the bytes are printable ASCII values.  Pass that result
 * into {@link #decode} and you'll get your original byte array.
 *
 * <p>Sincere thanks to Tom Daley for providing a sample encoder algorithm and a great
 * explanation of how RFC-1521 is supposed to work.
 *
 * @author Kelly
 */
public class Base64 {
	/** Encode into base 64.
	 *
	 * Encode the given data into RFC-1521 base 64.  Encoding a null array gives a
	 * null result.
	 *
	 * @param data The data to encode.
	 * @return Base-64 encoded <var>data</var>.
	 */
	public static byte[] encode(final byte[] data) {
		return encode(data, 0, data.length);
	}

	/** Encode into base 64.
	 *
	 * Encode the given data into RFC-1521 base 64.  Encoding a null array gives a
	 * null result.  Start encoding at the given offset and go for the given amount of
	 * bytes.
	 *
	 * @param data The data to encode.
	 * @param offset Where to start looking for data to encode.
	 * @param length How much data to encode.
	 * @return Base-64 encoded <var>data</var>
	 */
	public static byte[] encode(final byte[] data, int offset, int length) {
		if (data == null) return null;
		if (offset < 0 || offset > data.length)
			throw new IndexOutOfBoundsException("Can't encode at index " + offset + " which is beyond array bounds 0.."
				+ data.length);
		if (length < 0) throw new IllegalArgumentException("Can't encode a negative amount of data");
		if (offset + length > data.length)
			throw new IndexOutOfBoundsException("Can't encode beyond right edge of array");
		
		int i, j;
		byte dest[] = new byte[((length+2)/3)*4];

		// Convert groups of 3 bytes into 4.
		for (i = 0 + offset, j = 0; i < offset + length - 2; i += 3) {
			dest[j++] = (byte) ((data[i] >>> 2) & 077);
			dest[j++] = (byte) ((data[i+1] >>> 4) & 017 | (data[i] << 4) & 077);
			dest[j++] = (byte) ((data[i+2] >>> 6) & 003 | (data[i+1] << 2) & 077);
			dest[j++] = (byte) (data[i+2] & 077);
		}

		// Convert any leftover bytes.
		if (i < offset + length) {
			dest[j++] = (byte) ((data[i] >>> 2) & 077);
			if (i < offset + length - 1) {
				dest[j++] = (byte) ((data[i+1] >>> 4) & 017 | (data[i] << 4) & 077);
				dest[j++] = (byte) ((data[i+1] << 2) & 077);
			} else
				dest[j++] = (byte) ((data[i] << 4) & 077);
		}

		// Now, map those onto base 64 printable ASCII.
		for (i = 0; i <j; i++) {
			if      (dest[i] < 26)  dest[i] = (byte)(dest[i] + 'A');
			else if (dest[i] < 52)  dest[i] = (byte)(dest[i] + 'a'-26);
			else if (dest[i] < 62)  dest[i] = (byte)(dest[i] + '0'-52);
			else if (dest[i] < 63)  dest[i] = (byte) '+';
			else                    dest[i] = (byte) '/';
		}

		// Pad the result with and we're done.
		for (; i < dest.length; i++) dest[i] = (byte) '=';
		return dest;
	}

	/** Decode from base 64.
	 *
	 * Decode the given RFC-1521 base 64 encoded bytes into the original data they
	 * represent.  Decoding null data gives a null result.
	 *
	 * @param data Base-64 encoded data to decode.
	 * @return Decoded <var>data</var>.
	 */
	public static byte[] decode(final byte[] data) {
		return decode(data, 0, data.length);
	}

	/** Decode from base 64.
	 *
	 * Decode the given RFC-1521 base 64 encoded bytes into the original data they
	 * represent.  Decoding null data gives a null result.
	 *
	 * @param data Base-64 encoded data to decode.
	 * @param offset Where to start looking for data to decode.
	 * @param length How much data to decode.
	 * @return Decoded <var>data</var>.
	 */
	public static byte[] decode(final byte[] data, int offset, int length) {
		if (data == null) return null;
		if (offset < 0 || offset >= data.length)
			throw new IndexOutOfBoundsException("Can't decode at index " + offset + " which is beyond array bounds 0.."
				+ (data.length-1));
		if (length < 0) throw new IllegalArgumentException("Can't decode a negative amount of data");
		if (offset + length > data.length)
			throw new IndexOutOfBoundsException("Can't decode beyond right edge of array");

		// Ignore any padding at the end.
		int tail = offset + length - 1;
		while (tail >= offset && data[tail] == '=')
			--tail;
		byte dest[] = new byte[tail + offset + 1 - length/4];

		// First, convert from base-64 ascii to 6 bit bytes.
		for (int i = offset; i < offset+length; i++) {
			if      (data[i] == '=') data[i] = 0;
			else if (data[i] == '/') data[i] = 63;
			else if (data[i] == '+') data[i] = 62;
			else if (data[i] >= '0' && data[i] <= '9')
				data[i] = (byte)(data[i] - ('0' - 52));
			else if (data[i] >= 'a'  &&  data[i] <= 'z')
				data[i] = (byte)(data[i] - ('a' - 26));
			else if (data[i] >= 'A'  &&  data[i] <= 'Z')
				data[i] = (byte)(data[i] - 'A');
		}

		// Map those from 4 6-bit byte groups onto 3 8-bit byte groups.
		int i, j;
		for (i = 0 + offset, j = 0; j < dest.length - 2; i += 4, j += 3) {
			dest[j]   = (byte) (((data[i] << 2) & 255) | ((data[i+1] >>> 4) & 003));
			dest[j+1] = (byte) (((data[i+1] << 4) & 255) | ((data[i+2] >>> 2) & 017));
			dest[j+2] = (byte) (((data[i+2] << 6) & 255) | (data[i+3] & 077));
		}

		// And get the leftover ...
		if (j < dest.length)
			dest[j] = (byte) (((data[i] << 2) & 255) | ((data[i+1] >>> 4) & 003));
		if (++j < dest.length)
			dest[j] = (byte) (((data[i+1] << 4) & 255) | ((data[i+2] >>> 2) & 017));

		// That's it.
		return dest;
	}

	/** This class provides namespace for utility methods and shouldn't be instantiated.
	 */
	private Base64() {
		throw new IllegalStateException(getClass().getName() + " should not be instantiated");
	}

	/** Command-line runner that encodes or decodes.
	 *
	 * @param argv Command-line arguments.
	 */
	public static void main(String[] argv) throws Exception {
		if (argv.length < 1 || argv.length > 2) {
			System.err.println("Usage: encode|decode [file]");
			System.exit(1);
		}
		boolean encode = true;
		if ("encode".equals(argv[0]))
			encode = true;
		else if ("decode".equals(argv[0]))
			encode = false;
		else {
			System.err.println("Specify either \"encode\" or \"decode\"");
			System.exit(1);
		}
		InputStream source = argv.length == 2? new BufferedInputStream(new FileInputStream(argv[1])) : System.in;
		InputStream in;
		OutputStream out;
		if (encode) {
			in = source;
			out = new Base64EncodingOutputStream(System.out);
		} else {
			in = new Base64DecodingInputStream(source);
			out = System.out;
		}
		byte[] buf = new byte[512];
		int numRead;
		while ((numRead = in.read(buf)) != -1)
			out.write(buf, 0, numRead);
		in.close();
		out.close();
		System.exit(0);
	}
}

			
