/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.search.internal.core.text;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.content.IContentDescription;

import org.eclipse.core.resources.IFile;

/**
 *
 */
public class FileCharSequenceProvider {

	private static int NUMBER_OF_BUFFERS= 3;
	public static int BUFFER_SIZE= 2 << 18; // public for testing

	private FileCharSequence fReused= null;

	public CharSequence newCharSequence(IFile file) throws CoreException, IOException {
		if (fReused == null) {
			return new FileCharSequence(file);
		}
		FileCharSequence curr= fReused;
		fReused= null;
		curr.reset(file);
		return curr;
	}

	public void releaseCharSequence(CharSequence seq) throws IOException {
		if (seq instanceof FileCharSequence) {
			FileCharSequence curr= (FileCharSequence) seq;
			try {
				curr.close();
			} finally {
				if (fReused == null) {
					fReused= curr;
				}
			}
		}
	}

	public static class FileCharSequenceException extends RuntimeException {
		private static final long serialVersionUID= 1L;

		/* package */ FileCharSequenceException(IOException e) {
			super(e);
		}

		/* package */ FileCharSequenceException(CoreException e) {
			super(e);
		}

		public void throwWrappedException() throws CoreException, IOException {
			Throwable wrapped= getCause();
			if (wrapped instanceof CoreException) {
				throw (CoreException) wrapped;
			} else if (wrapped instanceof IOException) {
				throw (IOException) wrapped;
			}
			// not possible
		}
	}


	private static final class CharSubSequence implements CharSequence {

		private final int fSequenceOffset;
		private final int fSequenceLength;
		private final FileCharSequence fParent;

		public CharSubSequence(FileCharSequence parent, int offset, int length) {
			fParent= parent;
			fSequenceOffset= offset;
			fSequenceLength= length;
		}

		@Override
		public int length() {
			return fSequenceLength;
		}

		@Override
		public char charAt(int index) {
			if (index < 0) {
				throw new IndexOutOfBoundsException("index must be larger than 0"); //$NON-NLS-1$
			}
			if (index >= fSequenceLength) {
				throw new IndexOutOfBoundsException("index must be smaller than length"); //$NON-NLS-1$
			}
			return fParent.charAt(fSequenceOffset + index);
		}

		@Override
		public CharSequence subSequence(int start, int end) {
			if (end < start) {
				throw new IndexOutOfBoundsException("end cannot be smaller than start"); //$NON-NLS-1$
			}
			if (start < 0) {
				throw new IndexOutOfBoundsException("start must be larger than 0"); //$NON-NLS-1$
			}
			if (end > fSequenceLength) {
				throw new IndexOutOfBoundsException("end must be smaller or equal than length"); //$NON-NLS-1$
			}
			return fParent.subSequence(fSequenceOffset + start, fSequenceOffset + end);
		}

		@Override
		public String toString() {
			try {
				return fParent.getSubstring(fSequenceOffset,  fSequenceLength);
			} catch (IOException e) {
				throw new FileCharSequenceException(e);
			} catch (CoreException e) {
				throw new FileCharSequenceException(e);
			}
		}
	}


	private static final class Buffer {
		private final char[] fBuf;
		private int fOffset;
		private int fLength;

		private Buffer fNext;
		private Buffer fPrevious;

		public Buffer() {
			fBuf= new char[BUFFER_SIZE];
			reset();
			fNext= this;
			fPrevious= this;
		}

		public boolean contains(int pos) {
			int offset= fOffset;
			return offset <= pos && pos < offset + fLength;
		}

		/**
		 * Fills the buffer by reading from the given reader.
		 *
		 * @param reader the reader to read from
		 * @param pos the offset of the reader in the file
		 * @return returns true if the end of the file has been reached
		 * @throws IOException if reading from the buffer fails
		 */
		public boolean fill(Reader reader, int pos) throws IOException {
			int res= reader.read(fBuf);
			if (res == -1) {
				fOffset= pos;
				fLength= 0;
				return true;
			}

			int charsRead= res;
			while (charsRead < BUFFER_SIZE) {
				res= reader.read(fBuf, charsRead, BUFFER_SIZE - charsRead);
				if (res == -1) {
					fOffset= pos;
					fLength= charsRead;
					return true;
				}
				charsRead+= res;
			}
			fOffset= pos;
			fLength= BUFFER_SIZE;
			return false;
		}

		public char get(int pos) {
			return fBuf[pos - fOffset];
		}

		public StringBuilder append(StringBuilder buf, int start, int length) {
			return buf.append(fBuf, start - fOffset, length);
		}

		public StringBuilder appendAll(StringBuilder buf) {
			return buf.append(fBuf, 0, fLength);
		}

		public int getEndOffset() {
			return fOffset + fLength;
		}

		public void removeFromChain() {
			fPrevious.fNext= fNext;
			fNext.fPrevious= fPrevious;

			fNext= this;
			fPrevious= this;
		}

		public void insertBefore(Buffer other) {
			fNext= other;
			fPrevious= other.fPrevious;
			fPrevious.fNext= this;
			other.fPrevious= this;
		}

		public Buffer getNext() {
			return fNext;
		}

		public Buffer getPrevious() {
			return fPrevious;
		}

		public void reset() {
			fOffset= -1;
			fLength= 0;
		}
	}

	private final class FileCharSequence implements CharSequence {
		private Reader fReader;
		private int fReaderPos;

		private Integer fLength;

		private Buffer fMostCurrentBuffer; // access to the buffer chain
		private int fNumberOfBuffers;

		private IFile fFile;

		public FileCharSequence(IFile file) throws CoreException, IOException {
			fNumberOfBuffers= 0;
			reset(file);
		}

		public void reset(IFile file) throws CoreException, IOException {
			fFile= file;
			fLength= null; // only calculated on demand

			Buffer curr= fMostCurrentBuffer;
			if (curr != null) {
				do {
					curr.reset();
					curr= curr.getNext();
				} while (curr != fMostCurrentBuffer);
			}
			initializeReader();
		}

		private void initializeReader() throws CoreException, IOException {
			if (fReader != null) {
				fReader.close();
			}
			String charset= fFile.getCharset();
			fReader= new InputStreamReader(getInputStream(charset), charset);
			fReaderPos= 0;
		}

		private InputStream getInputStream(String charset) throws CoreException, IOException {
			boolean ok= false;
			InputStream contents= fFile.getContents();
			try {
				if (StandardCharsets.UTF_8.name().equals(charset)) {
					/*
					 * This is a workaround for a corresponding bug in Java readers and writer,
					 * see http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
					 * we remove the BOM before passing the stream to the reader
					 */
					IContentDescription description= fFile.getContentDescription();
					if ((description != null) && (description.getProperty(IContentDescription.BYTE_ORDER_MARK) != null)) {
						int bomLength= IContentDescription.BOM_UTF_8.length;
						byte[] bomStore= new byte[bomLength];
						int bytesRead= 0;
						do {
							int bytes= contents.read(bomStore, bytesRead, bomLength - bytesRead);
							if (bytes == -1)
								throw new IOException();
							bytesRead += bytes;
						} while (bytesRead < bomLength);

						if (!Arrays.equals(bomStore, IContentDescription.BOM_UTF_8)) {
							// discard file reader, we were wrong, no BOM -> new stream
							contents.close();
							contents= fFile.getContents();
						}
					}
				}
				ok= true;
			} finally {
				if (!ok && contents != null)
					try {
						contents.close();
					} catch (IOException ex) {
						// ignore
					}
			}
			return contents;
		}

		private void clearReader() throws IOException {
			if (fReader != null) {
				fReader.close();
			}
			fReader= null;
			fReaderPos= Integer.MAX_VALUE;
		}

		@Override
		public int length() {
			if (fLength == null) {
				try {
					getBuffer(Integer.MAX_VALUE);
				} catch (IOException e) {
					throw new FileCharSequenceException(e);
				} catch (CoreException e) {
					throw new FileCharSequenceException(e);
				}
			}
			return fLength.intValue();
		}

		private Buffer getBuffer(int pos) throws IOException, CoreException {
			Buffer curr= fMostCurrentBuffer;
			if (curr != null) {
				do {
					if (curr.contains(pos)) {
						return curr;
					}
					curr= curr.getNext();
				} while (curr != fMostCurrentBuffer);
			}

			Buffer buf= findBufferToUse();
			fillBuffer(buf, pos);
			if (buf.contains(pos)) {
				return buf;
			}
			return null;
		}

		private Buffer findBufferToUse() {
			if (fNumberOfBuffers < NUMBER_OF_BUFFERS) {
				fNumberOfBuffers++;
				Buffer newBuffer= new Buffer();
				if (fMostCurrentBuffer == null) {
					fMostCurrentBuffer= newBuffer;
					return newBuffer;
				}
				newBuffer.insertBefore(fMostCurrentBuffer); // insert before first
				return newBuffer;
			}
			return fMostCurrentBuffer.getPrevious();
		}

		private boolean fillBuffer(Buffer buffer, int pos) throws CoreException, IOException {
			if (fReaderPos > pos) {
				initializeReader();
			}

			do {
				boolean endReached= buffer.fill(fReader, fReaderPos);
				fReaderPos= buffer.getEndOffset();
				if (endReached) {
					fLength= Integer.valueOf(fReaderPos); // at least we know the size of the file now
					fReaderPos= Integer.MAX_VALUE; // will have to reset next time
					return true;
				}
			} while (fReaderPos <= pos);

			return true;
		}

		@Override
		public char charAt(final int index) {
			final Buffer current= fMostCurrentBuffer;
			if (current != null && current.contains(index)) {
				return current.get(index);
			}

			if (index < 0) {
				throw new IndexOutOfBoundsException("index must be larger than 0"); //$NON-NLS-1$
			}
			if (fLength != null && index >= fLength.intValue()) {
				throw new IndexOutOfBoundsException("index must be smaller than length"); //$NON-NLS-1$
			}

			try {
				final Buffer buffer= getBuffer(index);
				if (buffer == null) {
					throw new IndexOutOfBoundsException("index must be smaller than length"); //$NON-NLS-1$
				}
				if (buffer != fMostCurrentBuffer) {
					// move to first
					if (buffer.getNext() != fMostCurrentBuffer) { // already before the current?
						buffer.removeFromChain();
						buffer.insertBefore(fMostCurrentBuffer);
					}
					fMostCurrentBuffer= buffer;
				}
				return buffer.get(index);
			} catch (IOException e) {
				throw new FileCharSequenceException(e);
			} catch (CoreException e) {
				throw new FileCharSequenceException(e);
			}
		}

		public String getSubstring(int start, int length) throws IOException, CoreException {
			int pos= start;
			int endPos= start + length;

			if (fLength != null && endPos > fLength.intValue()) {
				throw new IndexOutOfBoundsException("end must be smaller than length"); //$NON-NLS-1$
			}

			StringBuilder res= new StringBuilder(length);

			Buffer buffer= getBuffer(pos);
			while (pos < endPos && buffer != null) {
				int bufEnd= buffer.getEndOffset();
				if (bufEnd >= endPos) {
					return buffer.append(res, pos, endPos - pos).toString();
				}
				buffer.append(res, pos, bufEnd - pos);
				pos= bufEnd;
				buffer= getBuffer(pos);
			}
			return res.toString();
		}


		@Override
		public CharSequence subSequence(int start, int end) {
			if (end < start) {
				throw new IndexOutOfBoundsException("end cannot be smaller than start"); //$NON-NLS-1$
			}
			if (start < 0) {
				throw new IndexOutOfBoundsException("start must be larger than 0"); //$NON-NLS-1$
			}
			if (fLength != null && end > fLength.intValue()) {
				throw new IndexOutOfBoundsException("end must be smaller than length"); //$NON-NLS-1$
			}
			return new CharSubSequence(this, start, end - start);
		}

		public void close() throws IOException {
			clearReader();
		}

		@Override
		public String toString() {
			int len= fLength != null ? fLength.intValue() : 4000;
			StringBuilder res= new StringBuilder(len);
			try {
				Buffer buffer= getBuffer(0);
				while (buffer != null) {
					buffer.appendAll(res);
					buffer= getBuffer(res.length());
				}
				return res.toString();
			} catch (IOException e) {
				throw new FileCharSequenceException(e);
			} catch (CoreException e) {
				throw new FileCharSequenceException(e);
			}
		}
	}

}
