// ***************************************************************************************************************************
// * 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.parser;

import static org.apache.juneau.internal.IOUtils.*;
import static org.apache.juneau.internal.StringUtils.*;

import java.io.*;
import java.nio.charset.*;

import org.apache.juneau.*;
import org.apache.juneau.internal.*;

/**
 * A wrapper around an object that a parser reads its input from.
 *
 * <p>
 * For character-based parsers, the input object can be any of the following:
 * <ul>
 * 	<li>{@link Reader}
 * 	<li>{@link CharSequence}
 * 	<li>{@link InputStream}
 * 	<li><code><jk>byte</jk>[]</code>
 * 	<li>{@link File}
 * 	<li><code><jk>null</jk></code>
 * </ul>
 *
 * <p>
 * For stream-based parsers, the input object can be any of the following:
 * <ul>
 * 	<li>{@link InputStream}
 * 	<li><code><jk>byte</jk>[]</code>
 * 	<li>{@link File}
 * 	<li>{@link String} - Hex-encoded bytes.  (not BASE-64!)
 * 	<li><code><jk>null</jk></code>
 * </ul>
 *
 * <p>
 * Note that Readers and InputStreams will NOT be automatically closed when {@link #close()} is called, but
 * streams and readers created from other types (e.g. Files) WILL be automatically closed.
 */
public final class ParserPipe implements Closeable {

	private final Object input;
	final boolean debug, strict, autoCloseStreams, unbuffered;
	private final Charset charset;

	private String inputString;
	private InputStream inputStream;
	private Reader reader;
	private ParserReader parserReader;
	private boolean doClose;
	private BinaryFormat binaryFormat;
	private Positionable positionable;

	/**
	 * Constructor for reader-based parsers.
	 *
	 * @param input The parser input object.
	 * @param debug
	 * 	If <jk>true</jk>, the input contents will be copied locally and accessible via the {@link #getInputAsString()}
	 * 	method.
	 * 	This allows the contents of the pipe to be accessed when a problem occurs.
	 * @param strict
	 * 	If <jk>true</jk>, sets {@link CodingErrorAction#REPORT} on {@link CharsetDecoder#onMalformedInput(CodingErrorAction)}
	 * 	and {@link CharsetDecoder#onUnmappableCharacter(CodingErrorAction)}.
	 * 	Otherwise, sets them to {@link CodingErrorAction#REPLACE}.
	 * @param autoCloseStreams
	 * 	Automatically close {@link InputStream InputStreams} and {@link Reader Readers} when passed in as input.
	 * @param unbuffered
	 * 	If <jk>true</jk>, we read one character at a time from underlying readers when the readers are expected to be parsed
	 * 	multiple times.
	 * 	<br>Otherwise, we read character data into a reusable buffer.
	 * @param fileCharset
	 * 	The charset to expect when reading from {@link File Files}.
	 * @param streamCharset
	 * 	The charset to expect when reading from {@link InputStream InputStreams}.
	 */
	public ParserPipe(Object input, boolean debug, boolean strict, boolean autoCloseStreams, boolean unbuffered, Charset streamCharset, Charset fileCharset) {
		boolean isFile = input instanceof File;
		this.input = input;
		this.debug = debug;
		this.strict = strict;
		this.autoCloseStreams = autoCloseStreams;
		this.unbuffered = unbuffered;
		Charset cs = isFile ? fileCharset : streamCharset;
		if (cs == null)
			cs = (isFile ? Charset.defaultCharset() : UTF8);
		this.charset = cs;
		if (input instanceof CharSequence)
			this.inputString = input.toString();
		this.binaryFormat = null;
	}

	/**
	 * Constructor for stream-based parsers.
	 *
	 * @param input The parser input object.
	 * @param debug
	 * 	If <jk>true</jk>, the input contents will be copied locally and accessible via the {@link #getInputAsString()}
	 * 	method.
	 * 	This allows the contents of the pipe to be accessed when a problem occurs.
	 * @param autoCloseStreams
	 * 	Automatically close {@link InputStream InputStreams} and {@link Reader Readers} when passed in as input.
	 * @param unbuffered
	 * 	If <jk>true</jk>, we read one character at a time from underlying readers when the readers are expected to be parsed
	 * 	multiple times.
	 * 	<br>Otherwise, we read character data into a reusable buffer.
	 * @param binaryFormat The binary format of input strings when converted to bytes.
	 */
	public ParserPipe(Object input, boolean debug, boolean autoCloseStreams, boolean unbuffered, BinaryFormat binaryFormat) {
		this.input = input;
		this.debug = debug;
		this.strict = false;
		this.autoCloseStreams = autoCloseStreams;
		this.unbuffered = unbuffered;
		this.charset = null;
		if (input instanceof CharSequence)
			this.inputString = input.toString();
		this.binaryFormat = binaryFormat;
	}

	/**
	 * Shortcut constructor, typically for straight string input.
	 *
	 * <p>
	 * Equivalent to calling <code><jk>new</jk> ParserPipe(input, <jk>false</jk>, <jk>false</jk>, <jk>null</jk>, <jk>null</jk>);</code>
	 *
	 * @param input The input object.
	 */
	public ParserPipe(Object input) {
		this(input, false, false, false, false, null, null);
	}

	/**
	 * Wraps the specified input object inside an input stream.
	 *
	 * <p>
	 * Subclasses can override this method to implement their own input streams.
	 *
	 * @return The input object wrapped in an input stream, or <jk>null</jk> if the object is null.
	 * @throws IOException If object could not be converted to an input stream.
	 */
	public InputStream getInputStream() throws IOException {
		if (input == null)
			return null;

		if (input instanceof InputStream) {
			if (debug) {
				byte[] b = readBytes((InputStream)input, 1024);
				inputString = toHex(b);
				inputStream = new ByteArrayInputStream(b);
			} else {
				inputStream = (InputStream)input;
				doClose = autoCloseStreams;
			}
		} else if (input instanceof byte[]) {
			if (debug)
				inputString = toHex((byte[])input);
			inputStream = new ByteArrayInputStream((byte[])input);
			doClose = false;
		} else if (input instanceof String) {
			inputString = (String)input;
			inputStream = new ByteArrayInputStream(convertFromString((String)input));
			doClose = false;
		} else if (input instanceof File) {
			if (debug) {
				byte[] b = readBytes((File)input);
				inputString = toHex(b);
				inputStream = new ByteArrayInputStream(b);
			} else {
				inputStream = new FileInputStream((File)input);
				doClose = true;
			}
		} else {
			throw new IOException("Cannot convert object of type "+input.getClass().getName()+" to an InputStream.");
		}

		return inputStream;
	}

	private byte[] convertFromString(String in) {
		switch(binaryFormat) {
			case BASE64: return base64Decode(in);
			case HEX: return fromHex(in);
			case SPACED_HEX: return fromSpacedHex(in);
			default:	return new byte[0];
		}
	}

	/**
	 * Wraps the specified input object inside a reader.
	 *
	 * <p>
	 * Subclasses can override this method to implement their own readers.
	 *
	 * @return The input object wrapped in a Reader, or <jk>null</jk> if the object is null.
	 * @throws IOException If object could not be converted to a reader.
	 */
	public Reader getReader() throws IOException {
		if (input == null)
			return null;

		if (input instanceof Reader) {
			if (debug) {
				inputString = read((Reader)input);
				reader = new StringReader(inputString);
			} else {
				reader = (Reader)input;
				doClose = autoCloseStreams;
			}
		} else if (input instanceof CharSequence) {
			inputString = input.toString();
			reader = new ParserReader(this);
			doClose = false;
		} else if (input instanceof InputStream || input instanceof byte[]) {
			doClose = input instanceof InputStream && autoCloseStreams;
			InputStream is = (
				input instanceof InputStream
				? (InputStream)input
				: new ByteArrayInputStream((byte[])input)
			);
			CharsetDecoder cd = charset.newDecoder();
			if (strict) {
				cd.onMalformedInput(CodingErrorAction.REPORT);
				cd.onUnmappableCharacter(CodingErrorAction.REPORT);
			} else {
				cd.onMalformedInput(CodingErrorAction.REPLACE);
				cd.onUnmappableCharacter(CodingErrorAction.REPLACE);
			}
			reader = new InputStreamReader(is, cd);
			if (debug) {
				inputString = read(reader);
				reader = new StringReader(inputString);
			}
		} else if (input instanceof File) {
			CharsetDecoder cd = charset.newDecoder();
			if (strict) {
				cd.onMalformedInput(CodingErrorAction.REPORT);
				cd.onUnmappableCharacter(CodingErrorAction.REPORT);
			} else {
				cd.onMalformedInput(CodingErrorAction.REPLACE);
				cd.onUnmappableCharacter(CodingErrorAction.REPLACE);
			}
			reader = new InputStreamReader(new FileInputStream((File)input), cd);
			if (debug) {
				inputString = read(reader);
				reader = new StringReader(inputString);
			}
			doClose = true;
		} else {
			throw new IOException("Cannot convert object of type "+input.getClass().getName()+" to a Reader.");
		}

		return reader;
	}

	/**
	 * Returns the contents of this pipe as a buffered reader.
	 *
	 * <p>
	 * If the reader passed into this pipe is already a buffered reader, that reader will be returned.
	 *
	 * @return The contents of this pipe as a buffered reader.
	 * @throws IOException Thrown by underlying stream.
	 */
	public Reader getBufferedReader() throws IOException {
		return IOUtils.getBufferedReader(getReader());
	}

	/**
	 * Returns the input to this parser as a plain string.
	 *
	 * <p>
	 * This method only returns a value if {@link BeanContext#BEAN_debug} is enabled.
	 *
	 * @return The input as a string, or <jk>null</jk> if debug mode not enabled.
	 */
	public String getInputAsString() {
		return inputString;
	}

	/**
	 * Converts this pipe into a {@link ParserReader}.
	 *
	 * @return The converted pipe.
	 * @throws IOException Thrown by underlying stream.
	 */
	public ParserReader getParserReader() throws IOException {
		if (input == null)
			return null;
		if (input instanceof ParserReader)
			parserReader = (ParserReader)input;
		else
			parserReader = new ParserReader(this);
		return parserReader;
	}

	/**
	 * Returns <jk>true</jk> if the contents passed into this pipe was a {@link CharSequence}.
	 *
	 * @return <jk>true</jk> if the contents passed into this pipe was a {@link CharSequence}.
	 */
	public boolean isString() {
		return inputString != null;
	}

	/**
	 * Sets the ParserReader/ParserInputStream/XmlReader constructed from this pipe.
	 *
	 * <p>
	 * Used for gathering the failure position when {@link ParseException} is thrown.
	 *
	 * @param positionable The ParserReader/ParserInputStream/XmlReader constructed from this pipe.
	 */
	public void setPositionable(Positionable positionable) {
		this.positionable = positionable;
	}

	Position getPosition() {
		if (positionable == null)
			return Position.UNKNOWN;
		Position p = positionable.getPosition();
		if (p == null)
			return Position.UNKNOWN;
		return p;
	}

	@Override /* Closeable */
	public void close() {
		try {
			if (doClose)
				IOUtils.close(reader, inputStream);
		} catch (IOException e) {
			throw new BeanRuntimeException(e);
		}
	}
}