/*
 * Copyright (C) 2008-2009, Google Inc.
 * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.util;

import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.util.io.SilentFileInputStream;

/**
 * Input/Output utilities
 */
public class IO {

	/**
	 * Read an entire local file into memory as a byte array.
	 *
	 * @param path
	 *            location of the file to read.
	 * @return complete contents of the requested local file.
	 * @throws java.io.FileNotFoundException
	 *             the file does not exist.
	 * @throws java.io.IOException
	 *             the file exists, but its contents cannot be read.
	 */
	public static final byte[] readFully(File path)
			throws FileNotFoundException, IOException {
		return IO.readFully(path, Integer.MAX_VALUE);
	}

	/**
	 * Read at most limit bytes from the local file into memory as a byte array.
	 *
	 * @param path
	 *            location of the file to read.
	 * @param limit
	 *            maximum number of bytes to read, if the file is larger than
	 *            only the first limit number of bytes are returned
	 * @return complete contents of the requested local file. If the contents
	 *         exceeds the limit, then only the limit is returned.
	 * @throws java.io.FileNotFoundException
	 *             the file does not exist.
	 * @throws java.io.IOException
	 *             the file exists, but its contents cannot be read.
	 */
	public static final byte[] readSome(File path, int limit)
			throws FileNotFoundException, IOException {
		try (SilentFileInputStream in = new SilentFileInputStream(path)) {
			byte[] buf = new byte[limit];
			int cnt = 0;
			for (;;) {
				int n = in.read(buf, cnt, buf.length - cnt);
				if (n <= 0)
					break;
				cnt += n;
			}
			if (cnt == buf.length)
				return buf;
			byte[] res = new byte[cnt];
			System.arraycopy(buf, 0, res, 0, cnt);
			return res;
		}
	}

	/**
	 * Read an entire local file into memory as a byte array.
	 *
	 * @param path
	 *            location of the file to read.
	 * @param max
	 *            maximum number of bytes to read, if the file is larger than
	 *            this limit an IOException is thrown.
	 * @return complete contents of the requested local file.
	 * @throws java.io.FileNotFoundException
	 *             the file does not exist.
	 * @throws java.io.IOException
	 *             the file exists, but its contents cannot be read.
	 */
	public static final byte[] readFully(File path, int max)
			throws FileNotFoundException, IOException {
		try (SilentFileInputStream in = new SilentFileInputStream(path)) {
			long sz = Math.max(path.length(), 1);
			if (sz > max)
				throw new IOException(MessageFormat.format(
						JGitText.get().fileIsTooLarge, path));

			byte[] buf = new byte[(int) sz];
			int valid = 0;
			for (;;) {
				if (buf.length == valid) {
					if (buf.length == max) {
						int next = in.read();
						if (next < 0)
							break;

						throw new IOException(MessageFormat.format(
								JGitText.get().fileIsTooLarge, path));
					}

					byte[] nb = new byte[Math.min(buf.length * 2, max)];
					System.arraycopy(buf, 0, nb, 0, valid);
					buf = nb;
				}
				int n = in.read(buf, valid, buf.length - valid);
				if (n < 0)
					break;
				valid += n;
			}
			if (valid < buf.length) {
				byte[] nb = new byte[valid];
				System.arraycopy(buf, 0, nb, 0, valid);
				buf = nb;
			}
			return buf;
		}
	}

	/**
	 * Read an entire input stream into memory as a ByteBuffer.
	 *
	 * Note: The stream is read to its end and is not usable after calling this
	 * method. The caller is responsible for closing the stream.
	 *
	 * @param in
	 *            input stream to be read.
	 * @param sizeHint
	 *            a hint on the approximate number of bytes contained in the
	 *            stream, used to allocate temporary buffers more efficiently
	 * @return complete contents of the input stream. The ByteBuffer always has
	 *         a writable backing array, with {@code position() == 0} and
	 *         {@code limit()} equal to the actual length read. Callers may rely
	 *         on obtaining the underlying array for efficient data access. If
	 *         {@code sizeHint} was too large, the array may be over-allocated,
	 *         resulting in {@code limit() < array().length}.
	 * @throws java.io.IOException
	 *             there was an error reading from the stream.
	 */
	public static ByteBuffer readWholeStream(InputStream in, int sizeHint)
			throws IOException {
		byte[] out = new byte[sizeHint];
		int pos = 0;
		while (pos < out.length) {
			int read = in.read(out, pos, out.length - pos);
			if (read < 0)
				return ByteBuffer.wrap(out, 0, pos);
			pos += read;
		}

		int last = in.read();
		if (last < 0)
			return ByteBuffer.wrap(out, 0, pos);

		try (TemporaryBuffer.Heap tmp = new TemporaryBuffer.Heap(
				Integer.MAX_VALUE)) {
			tmp.write(out);
			tmp.write(last);
			tmp.copy(in);
			return ByteBuffer.wrap(tmp.toByteArray());
		}
	}

	/**
	 * Read the entire byte array into memory, or throw an exception.
	 *
	 * @param fd
	 *            input stream to read the data from.
	 * @param dst
	 *            buffer that must be fully populated, [off, off+len).
	 * @param off
	 *            position within the buffer to start writing to.
	 * @param len
	 *            number of bytes that must be read.
	 * @throws EOFException
	 *             the stream ended before dst was fully populated.
	 * @throws java.io.IOException
	 *             there was an error reading from the stream.
	 */
	public static void readFully(final InputStream fd, final byte[] dst,
			int off, int len) throws IOException {
		while (len > 0) {
			final int r = fd.read(dst, off, len);
			if (r <= 0)
				throw new EOFException(JGitText.get().shortReadOfBlock);
			off += r;
			len -= r;
		}
	}

	/**
	 * Read as much of the array as possible from a channel.
	 *
	 * @param channel
	 *            channel to read data from.
	 * @param dst
	 *            buffer that must be fully populated, [off, off+len).
	 * @param off
	 *            position within the buffer to start writing to.
	 * @param len
	 *            number of bytes that should be read.
	 * @return number of bytes actually read.
	 * @throws java.io.IOException
	 *             there was an error reading from the channel.
	 */
	public static int read(ReadableByteChannel channel, byte[] dst, int off,
			int len) throws IOException {
		if (len == 0)
			return 0;
		int cnt = 0;
		while (0 < len) {
			int r = channel.read(ByteBuffer.wrap(dst, off, len));
			if (r <= 0)
				break;
			off += r;
			len -= r;
			cnt += r;
		}
		return cnt != 0 ? cnt : -1;
	}

	/**
	 * Read the entire byte array into memory, unless input is shorter
	 *
	 * @param fd
	 *            input stream to read the data from.
	 * @param dst
	 *            buffer that must be fully populated, [off, off+len).
	 * @param off
	 *            position within the buffer to start writing to.
	 * @return number of bytes in buffer or stream, whichever is shortest
	 * @throws java.io.IOException
	 *             there was an error reading from the stream.
	 */
	public static int readFully(InputStream fd, byte[] dst, int off)
			throws IOException {
		int r;
		int len = 0;
		while ((r = fd.read(dst, off, dst.length - off)) >= 0
				&& len < dst.length) {
			off += r;
			len += r;
		}
		return len;
	}

	/**
	 * Skip an entire region of an input stream.
	 * <p>
	 * The input stream's position is moved forward by the number of requested
	 * bytes, discarding them from the input. This method does not return until
	 * the exact number of bytes requested has been skipped.
	 *
	 * @param fd
	 *            the stream to skip bytes from.
	 * @param toSkip
	 *            total number of bytes to be discarded. Must be &gt;= 0.
	 * @throws EOFException
	 *             the stream ended before the requested number of bytes were
	 *             skipped.
	 * @throws java.io.IOException
	 *             there was an error reading from the stream.
	 */
	public static void skipFully(InputStream fd, long toSkip)
			throws IOException {
		while (toSkip > 0) {
			final long r = fd.skip(toSkip);
			if (r <= 0)
				throw new EOFException(JGitText.get().shortSkipOfBlock);
			toSkip -= r;
		}
	}

	/**
	 * Divides the given string into lines.
	 *
	 * @param s
	 *            the string to read
	 * @return the string divided into lines
	 * @since 2.0
	 */
	public static List<String> readLines(String s) {
		List<String> l = new ArrayList<>();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (c == '\n') {
				l.add(sb.toString());
				sb.setLength(0);
				continue;
			}
			if (c == '\r') {
				if (i + 1 < s.length()) {
					c = s.charAt(++i);
					l.add(sb.toString());
					sb.setLength(0);
					if (c != '\n')
						sb.append(c);
					continue;
				} else { // EOF
					l.add(sb.toString());
					break;
				}
			}
			sb.append(c);
		}
		l.add(sb.toString());
		return l;
	}

	/**
	 * Read the next line from a reader.
	 * <p>
	 * Like {@link java.io.BufferedReader#readLine()}, but only treats
	 * {@code \n} as end-of-line, and includes the trailing newline.
	 *
	 * @param in
	 *            the reader to read from.
	 * @param sizeHint
	 *            hint for buffer sizing; 0 or negative for default.
	 * @return the next line from the input, always ending in {@code \n} unless
	 *         EOF was reached.
	 * @throws java.io.IOException
	 *             there was an error reading from the stream.
	 * @since 4.1
	 */
	public static String readLine(Reader in, int sizeHint) throws IOException {
		if (in.markSupported()) {
			if (sizeHint <= 0) {
				sizeHint = 1024;
			}
			StringBuilder sb = new StringBuilder(sizeHint);
			char[] buf = new char[sizeHint];
			while (true) {
				in.mark(sizeHint);
				int n = in.read(buf);
				if (n < 0) {
					in.reset();
					return sb.toString();
				}
				for (int i = 0; i < n; i++) {
					if (buf[i] == '\n') {
						resetAndSkipFully(in, ++i);
						sb.append(buf, 0, i);
						return sb.toString();
					}
				}
				if (n > 0) {
					sb.append(buf, 0, n);
				}
				resetAndSkipFully(in, n);
			}
		} else {
			StringBuilder buf = sizeHint > 0
					? new StringBuilder(sizeHint)
					: new StringBuilder();
			int i;
			while ((i = in.read()) != -1) {
				char c = (char) i;
				buf.append(c);
				if (c == '\n') {
					break;
				}
			}
			return buf.toString();
		}
	}

	private static void resetAndSkipFully(Reader fd, long toSkip) throws IOException {
		fd.reset();
		while (toSkip > 0) {
			long r = fd.skip(toSkip);
			if (r <= 0) {
				throw new EOFException(JGitText.get().shortSkipOfBlock);
			}
			toSkip -= r;
		}
	}

	private IO() {
		// Don't create instances of a static only utility.
	}
}
