/*
 * Copyright (C) 2005-2006 Kouji Sugisawa. All rights reserved.
 */

package jp.sourceforge.livez.lang;

import sun.io.ByteToCharConverter;
import sun.io.ConversionBufferFullException;
import sun.io.MalformedInputException;
import sun.io.UnknownCharacterException;

/**
 * UTF-7 のデコーダです。
 * 
 * @author 杉澤 浩二
 * @deprecated 未検証
 */
public final class ByteToCharUTF7 extends ByteToCharConverter {

	private boolean b64Context = false;
	private int currentB64Off = 0;
	private char currentChar = 0;

	public void reset() {
		byteOff = 0;
		charOff = 0;
		b64Context = false;
		currentB64Off = 0;
		currentChar = 0;
	}

	public int convert(final byte[] bytes, final int byteStart, final int byteEnd,
		final char[] chars, final int charStart, final int charEnd)
		throws MalformedInputException, UnknownCharacterException, ConversionBufferFullException {

		charOff = charStart;

		for (byteOff = byteStart; byteOff < byteEnd; byteOff++) {
			if (charOff >= charEnd)
				throw new ConversionBufferFullException();

			if (b64Context) {
				if (bytes[byteOff] == '-') {
					if (currentB64Off != 0 && currentChar > 0) {
						chars[charOff] = currentChar;
						charOff++;
					}
					b64Context = false;
					continue;
				}
				int part = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").indexOf(bytes[byteOff]);
				if (part == -1)
					throw new UnknownCharacterException("Invalid UTF-7 code: " + (char) bytes[byteOff]);

				switch (currentB64Off) {
					case 0:
						currentChar = (char)(part << 10);
						break;
					case 1:
						currentChar |= (char)(part << 4);
						break;
					case 2:
						currentChar |= (char)(part >> 2);
						chars[charOff] = currentChar;
						charOff++;
						currentChar = (char)((part & 0x03) << 14);
						break;
					case 3:
						currentChar |= (char)(part << 8);
						break;
					case 4:
						currentChar |= (char)(part << 2);
						break;
					case 5:
						currentChar |= (char)(part >> 4);
						chars[charOff] = currentChar;
						charOff++;
						currentChar = (char)((part & 0x0f) << 12);
						break;
					case 6:
						currentChar |= (char)(part << 6);
						break;
					case 7:
						currentChar |= (char) part;
						chars[charOff] = currentChar;
						charOff++;
						break;
				}
				currentB64Off = (currentB64Off + 1) % 8;
				continue;
			}

			if (bytes[byteOff] =='+') {
				// shift character
				// This is start of the Base64 sequence.
				b64Context = true;
				currentB64Off = 0;
				continue;
			}
			chars[charOff] = (char) bytes[byteOff];
			charOff++;
		}

		return charOff - charStart;
	}

	public int flush(final char[] chars, final int off, final int len) throws MalformedInputException, ConversionBufferFullException {
		byteOff = 0;
		charOff = 0;
		b64Context = false;
		currentB64Off = 0;
		currentChar = 0;
		return 0;
	}

	public String getCharacterEncoding() {
		return "UTF7";
	}

}
