// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE 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.juneau.uon;

import java.io.*;

import org.apache.juneau.parser.*;

/**
 * Same functionality as {@link ParserReader} except automatically decoded <c>%xx</c> escape sequences.
 *
 * <p>
 * Escape sequences are assumed to be encoded UTF-8.  Extended Unicode (&gt;\u10000) is supported.
 *
 * <p>
 * If decoding is enabled, the following character replacements occur so that boundaries are not lost:
 * <ul>
 * 	<li><js>'&amp;'</js> -&gt; <js>'\u0001'</js>
 * 	<li><js>'='</js> -&gt; <js>'\u0002'</js>
 * </ul>
 */
public final class UonReader extends ParserReader {

	private final boolean decodeChars;
	private final char[] buff;

	// Writable properties.
	private int iCurrent, iEnd;


	/**
	 * Constructor.
	 *
	 * @param pipe The parser input.
	 * @param decodeChars Whether the input is URL-encoded.
	 * @throws IOException Thrown by underlying stream.
	 */
	public UonReader(ParserPipe pipe, boolean decodeChars) throws IOException {
		super(pipe);
		this.decodeChars = decodeChars;
		if (pipe.isString()) {
			String in = pipe.getInputAsString();
			this.buff = new char[in.length() < 1024 ? in.length() : 1024];
		} else {
			this.buff = new char[1024];
		}
	}

	@Override /* Reader */
	public final int read(char[] cbuf, int off, int len) throws IOException {

		if (! decodeChars)
			return super.read(cbuf, off, len);

		// Copy any remainder to the beginning of the buffer.
		int remainder = iEnd - iCurrent;
		if (remainder > 0)
			System.arraycopy(buff, iCurrent, buff, 0, remainder);
		iCurrent = 0;

		int expected = buff.length - remainder;

		int x = super.read(buff, remainder, expected);
		if (x == -1 && remainder == 0)
			return -1;

		iEnd = remainder + (x == -1 ? 0 : x);

		int i = 0;
		while (i < len) {
			if (iCurrent >= iEnd)
				return i;
			char c = buff[iCurrent++];
			if (c == '+') {
				cbuf[off + i++] = ' ';
			} else if (c == '&') {
				cbuf[off + i++] = '\u0001';
			} else if (c == '=') {
				cbuf[off + i++] = '\u0002';
			} else if (c != '%') {
				cbuf[off + i++] = c;
			} else {
				int iMark = iCurrent-1;  // Keep track of current position.

				// Stop if there aren't at least two more characters following '%' in the buffer,
				// or there aren't at least two more positions open in cbuf to handle double-char chars.
				if (iMark+2 >= iEnd || i+2 > len) {
					iCurrent--;
					return i;
				}

				int b0 = readEncodedByte();
				int cx;

				// 0xxxxxxx
				if (b0 < 128) {
					cx = b0;

				// 10xxxxxx
				} else if (b0 < 192) {
					throw new IOException("Invalid hex value for first escape pattern in UTF-8 sequence:  " + b0);

				// 110xxxxx	10xxxxxx
				// 11000000(192) - 11011111(223)
				} else if (b0 < 224) {
					cx = readUTF8(b0-192, 1);
					if (cx == -1) {
						iCurrent = iMark;
						return i;
					}

				// 1110xxxx	10xxxxxx	10xxxxxx
				// 11100000(224) - 11101111(239)
				} else if (b0 < 240) {
					cx = readUTF8(b0-224, 2);
					if (cx == -1) {
						iCurrent = iMark;
						return i;
					}

				// 11110xxx	10xxxxxx	10xxxxxx	10xxxxxx
				// 11110000(240) - 11110111(247)
				} else if (b0 < 248) {
					cx = readUTF8(b0-240, 3);
					if (cx == -1) {
						iCurrent = iMark;
						return i;
					}

				} else
					throw new IOException("Invalid hex value for first escape pattern in UTF-8 sequence:  " + b0);

				if (cx < 0x10000)
					cbuf[off + i++] = (char)cx;
				else {
					cx -= 0x10000;
					cbuf[off + i++] = (char)(0xd800 + (cx >> 10));
					cbuf[off + i++] = (char)(0xdc00 + (cx & 0x3ff));
				}
			}
		}
		return i;
	}

	private int readUTF8(int n, final int numBytes) throws IOException {
		if (iCurrent + numBytes*3 > iEnd)
			return -1;
		for (int i = 0; i < numBytes; i++) {
			n <<= 6;
			n += readHex()-128;
		}
		return n;
	}

	private int readHex() throws IOException {
		int c = buff[iCurrent++];
		if (c != '%')
			throw new IOException("Did not find expected '%' character in UTF-8 sequence.");
		return readEncodedByte();
	}

	private int readEncodedByte() throws IOException {
		if (iEnd <= iCurrent + 1)
			throw new IOException("Incomplete trailing escape pattern");
		int h = buff[iCurrent++];
		int l = buff[iCurrent++];
		h = fromHexChar(h);
		l = fromHexChar(l);
		return (h << 4) + l;
	}

	private static int fromHexChar(int c) throws IOException {
		if (c >= '0' && c <= '9')
			return c - '0';
		if (c >= 'a' && c <= 'f')
			return 10 + c - 'a';
		if (c >= 'A' && c <= 'F')
			return 10 + c - 'A';
		throw new IOException("Invalid hex character '"+c+"' found in escape pattern.");
	}

	@Override /* ParserReader */
	public final UonReader unread() throws IOException {
		super.unread();
		return this;
	}
}
