/**
 * Copyright 2008-2010 DRIVER PROJECT (Bielefeld University)
 * Original author: Marek Imialek <marek.imialek at uni-bielefeld.de>
 *
 * Licensed 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 eu.dnetlib.miscutils.base64;

import sun.misc.BASE64Decoder;

/**
 * The Class base64Handler offers methods encoding and decoding string from/to base64
 * @author <a href="mailto:marek.imialek at uni-bielefeld.de">Marek Imialek</a>
 * 
 */
public class base64Handler {

	/** The base64code. */
	private static String base64code = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +

			"abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/";

	/** The split lines at. */
	private static int splitLinesAt = 76;

	/**
	 * Method encodes string to base64.
	 * 
	 * @param string string to be encoded
	 * @return base64 encoded string
	 */
	public static String encode(String string) {

		String encoded = "";
		byte[] stringArray;
		try {
			stringArray = string.getBytes("UTF-8");		
		} catch (Exception ignored) {
			stringArray = string.getBytes();
		}

		int paddingCount = (3 - (stringArray.length % 3)) % 3;
		
		stringArray = zeroPad(stringArray.length + paddingCount, stringArray);
		
		for (int i = 0; i < stringArray.length; i += 3) {
			int j = (stringArray[i] << 16) + (stringArray[i + 1] << 8)
					+ stringArray[i + 2];
			encoded = encoded + base64code.charAt((j >> 18) & 0x3f)
					+ base64code.charAt((j >> 12) & 0x3f)
					+ base64code.charAt((j >> 6) & 0x3f)
					+ base64code.charAt(j & 0x3f);
		}
		
		return splitLines(encoded.substring(0, encoded.length() - paddingCount)
				+ "==".substring(0, paddingCount));
	}
	
	/**
	 * Method decodes string from base64.
	 * @param string string to be decoded
	 * @return return decoded string
	 */
	public static String decode(String string) throws Exception{
		if (string==null)
			return null;
		
		BASE64Decoder decoder = new BASE64Decoder();
		string = string.replace(' ','\n');
		return new String(decoder.decodeBuffer(string));
	}
	

	/**
	 * Zero pad.
	 * 
	 * @param length
	 *            the length
	 * @param bytes
	 *            the bytes
	 * 
	 * @return the byte[]
	 */
	private static byte[] zeroPad(int length, byte[] bytes) {
		byte[] padded = new byte[length]; // initialized to zero by JVM
		System.arraycopy(bytes, 0, padded, 0, bytes.length);
		return padded;
	}

	/**
	 * Split lines.
	 * 
	 * @param string
	 *            the string
	 * 
	 * @return the string
	 */
	private static String splitLines(String string) {

		String lines = "";
		for (int i = 0; i < string.length(); i += splitLinesAt) {

			lines += string.substring(i, Math.min(string.length(), i
					+ splitLinesAt));
			lines += "\r\n";

		}
		return lines;

	}
}
