package org.tinylog.impl.writers.file;

import java.io.Closeable;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Path;

/**
 * Buffered text file writer.
 */
public class LogFile implements Closeable {

	private final RandomAccessFile file;
	private final boolean newFile;

	private final int bufferCapacity;
	private final ByteBuffer buffer;

	/**
	 * @param path The path to the log file
	 * @param bufferCapacity The capacity for the byte buffer (must be greater than 0)
	 * @param append {@code true} for appending an already existing file, {@code false} for overwriting an already
	 *               existing file
	 * @throws IOException Failed to open the log file
	 */
	public LogFile(Path path, int bufferCapacity, boolean append) throws IOException {
		this.file = new RandomAccessFile(path.toString(), "rw");

		if (append) {
			long fileLength = this.file.length();
			long maxBufferSize = bufferCapacity - (fileLength % bufferCapacity);

			this.buffer = new ByteBuffer(bufferCapacity, (int) maxBufferSize);
			this.bufferCapacity = bufferCapacity;

			if (fileLength == 0) {
				this.newFile = true;
			} else {
				this.newFile = false;
				this.file.seek(fileLength);
			}
		} else {
			this.newFile = true;
			this.file.setLength(0);

			this.buffer = new ByteBuffer(bufferCapacity, bufferCapacity);
			this.bufferCapacity = bufferCapacity;
		}
	}

	/**
	 * Checks if this log file has started as a new empty file or is appending an already existing file.
	 *
	 * @return {@code true} if this log file has started as a new empty file or {@code false} if it is appending an
	 *         already existing file
	 */
	public boolean isNewFile() {
		return newFile;
	}

	/**
	 * Writes a byte array into the log file.
	 *
	 * @param data The bytes to write
	 * @param start The starting position in the passed source byte array
	 * @throws IOException Failed to write into the log file
	 */
	public void write(byte[] data, int start) throws IOException {
		int bytes = buffer.store(data, start);

		if (buffer.isFull()) {
			buffer.writeTo(file);
			buffer.reset(bufferCapacity);

			int remainingChunks = (data.length - start - bytes) / bufferCapacity;
			if (remainingChunks > 0) {
				int length = remainingChunks * bufferCapacity;
				file.write(data, bytes, length);
				bytes += length;
			}

			if (bytes < data.length - start) {
				buffer.store(data, bytes);
			}
		}
	}

	/**
	 * Writes all buffered data into the log file.
	 *
	 * @throws IOException Failed to write into the log file
	 */
	public void flush() throws IOException {
		if (!buffer.isEmpty()) {
			int remaining = buffer.writeTo(file);
			buffer.reset(remaining == 0 ? bufferCapacity : remaining);
		}
	}

	/**
	 * Closes the log file. All buffered data will be written before closing.
	 *
	 * @throws IOException Failed to write into the log file
	 */
	@Override
	public void close() throws IOException {
		try {
			flush();
		} finally {
			file.close();
		}
	}

}

@@ -116,24 +116,52 @@
 AccessFile;%0A
+import java.nio.file.Files;%0A
 import java.
@@ -815,16 +815,69 @@
 ption %7B%0A
+%09%09if (!append) %7B%0A%09%09%09Files.deleteIfExists(path);%0A%09%09%7D%0A%0A
 %09%09this.f
@@ -914,14 +914,12 @@
 h.to
-String
+File
 (), 
@@ -930,25 +930,8 @@
 );%0A%0A
-%09%09if (append) %7B%0A%09
 %09%09lo
@@ -968,17 +968,16 @@
 th();%0A%09%09
-%09
 long max
@@ -1036,25 +1036,24 @@
 pacity);%0A%0A%09%09
-%09
 this.buffer 
@@ -1107,17 +1107,16 @@
 rSize);%0A
-%09
 %09%09this.b
@@ -1154,304 +1154,69 @@
 %0A%0A%09%09
-%09if (fileLength == 0) %7B%0A%09%09%09%09this.newFile = true;%0A%09%09%09%7D else %7B%0A%09%09%09%09this.newFile = false;%0A%09%09%09%09this.file.seek(fileLength);%0A%09%09%09%7D%0A%09%09%7D else %7B%0A%09%09%09this.newFile = true;%0A%09%09%09this.file.setLength(0);%0A%0A%09%09%09this.buffer = new ByteBuffer(bufferCapacity, bufferCapacity);%0A%09%09%09this.bufferCapacity = bufferCapacity;%0A%09%09%7D
+this.newFile = fileLength == 0;%0A%09%09this.file.seek(fileLength);
 %0A%09%7D%0A

Simplify constructor of Logfile