/*
 * Copyright (C) 2008-2009, Google Inc. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.patch;

import static org.eclipse.jgit.util.RawParseUtils.match;
import static org.eclipse.jgit.util.RawParseUtils.nextLF;
import static org.eclipse.jgit.util.RawParseUtils.parseBase10;

import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;

import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.util.MutableInteger;

/**
 * Hunk header describing the layout of a single block of lines
 */
public class HunkHeader {
	/** Details about an old image of the file. */
	public abstract static class OldImage {
		/** First line number the hunk starts on in this file. */
		int startLine;

		/** Total number of lines this hunk covers in this file. */
		int lineCount;

		/** Number of lines deleted by the post-image from this file. */
		int nDeleted;

		/** Number of lines added by the post-image not in this file. */
		int nAdded;

		/**
		 * Get line number where hunk starts
		 *
		 * @return first line number the hunk starts on in this file.
		 */
		public int getStartLine() {
			return startLine;
		}

		/**
		 * Get number of lines this hunk covers
		 *
		 * @return total number of lines this hunk covers in this file.
		 */
		public int getLineCount() {
			return lineCount;
		}

		/**
		 * Get number of lines deleted by the post-image
		 *
		 * @return number of lines deleted by the post-image from this file.
		 */
		public int getLinesDeleted() {
			return nDeleted;
		}

		/**
		 * Get number of lines added by the post-image
		 *
		 * @return number of lines added by the post-image not in this file.
		 */
		public int getLinesAdded() {
			return nAdded;
		}

		/**
		 * Get id of the pre-image file
		 *
		 * @return object id of the pre-image file.
		 */
		public abstract AbbreviatedObjectId getId();
	}

	final FileHeader file;

	/** Offset within {@link #file}.buf to the "@@ -" line. */
	final int startOffset;

	/** Position 1 past the end of this hunk within {@link #file}'s buf. */
	int endOffset;

	private final OldImage old;

	/** First line number in the post-image file where the hunk starts */
	int newStartLine;

	/** Total number of post-image lines this hunk covers (context + inserted) */
	int newLineCount;

	/** Total number of lines of context appearing in this hunk */
	int nContext;

	private EditList editList;

	HunkHeader(FileHeader fh, int offset) {
		this(fh, offset, new OldImage() {
			@Override
			public AbbreviatedObjectId getId() {
				return fh.getOldId();
			}
		});
	}

	HunkHeader(FileHeader fh, int offset, OldImage oi) {
		file = fh;
		startOffset = offset;
		old = oi;
	}

	HunkHeader(FileHeader fh, EditList editList) {
		this(fh, fh.buf.length);
		this.editList = editList;
		endOffset = startOffset;
		nContext = 0;
		if (editList.isEmpty()) {
			newStartLine = 0;
			newLineCount = 0;
		} else {
			newStartLine = editList.get(0).getBeginB();
			Edit last = editList.get(editList.size() - 1);
			newLineCount = last.getEndB() - newStartLine;
		}
	}

	/**
	 * Get header for the file this hunk applies to.
	 *
	 * @return header for the file this hunk applies to.
	 */
	public FileHeader getFileHeader() {
		return file;
	}

	/**
	 * Get the byte array holding this hunk's patch script.
	 *
	 * @return the byte array holding this hunk's patch script.
	 */
	public byte[] getBuffer() {
		return file.buf;
	}

	/**
	 * Get offset of the start of this hunk in {@link #getBuffer()}.
	 *
	 * @return offset of the start of this hunk in {@link #getBuffer()}.
	 */
	public int getStartOffset() {
		return startOffset;
	}

	/**
	 * Get offset one past the end of the hunk in {@link #getBuffer()}.
	 *
	 * @return offset one past the end of the hunk in {@link #getBuffer()}.
	 */
	public int getEndOffset() {
		return endOffset;
	}

	/**
	 * Get information about the old image mentioned in this hunk.
	 *
	 * @return information about the old image mentioned in this hunk.
	 */
	public OldImage getOldImage() {
		return old;
	}

	/**
	 * Get first line number in the post-image file where the hunk starts.
	 *
	 * @return first line number in the post-image file where the hunk starts.
	 */
	public int getNewStartLine() {
		return newStartLine;
	}

	/**
	 * Get total number of post-image lines this hunk covers.
	 *
	 * @return total number of post-image lines this hunk covers.
	 */
	public int getNewLineCount() {
		return newLineCount;
	}

	/**
	 * Get total number of lines of context appearing in this hunk.
	 *
	 * @return total number of lines of context appearing in this hunk.
	 */
	public int getLinesContext() {
		return nContext;
	}

	/**
	 * Convert to a list describing the content edits performed within the hunk.
	 *
	 * @return a list describing the content edits performed within the hunk.
	 */
	public EditList toEditList() {
		if (editList == null) {
			editList = new EditList();
			final byte[] buf = file.buf;
			int c = nextLF(buf, startOffset);
			int oLine = old.startLine;
			int nLine = newStartLine;
			Edit in = null;

			SCAN: for (; c < endOffset; c = nextLF(buf, c)) {
				switch (buf[c]) {
				case ' ':
				case '\n':
					in = null;
					oLine++;
					nLine++;
					continue;

				case '-':
					if (in == null) {
						in = new Edit(oLine - 1, nLine - 1);
						editList.add(in);
					}
					oLine++;
					in.extendA();
					continue;

				case '+':
					if (in == null) {
						in = new Edit(oLine - 1, nLine - 1);
						editList.add(in);
					}
					nLine++;
					in.extendB();
					continue;

				case '\\': // Matches "\ No newline at end of file"
					continue;

				default:
					break SCAN;
				}
			}
		}
		return editList;
	}

	void parseHeader() {
		// Parse "@@ -236,9 +236,9 @@ protected boolean"
		//
		final byte[] buf = file.buf;
		final MutableInteger ptr = new MutableInteger();
		ptr.value = nextLF(buf, startOffset, ' ');
		old.startLine = -parseBase10(buf, ptr.value, ptr);
		if (buf[ptr.value] == ',')
			old.lineCount = parseBase10(buf, ptr.value + 1, ptr);
		else
			old.lineCount = 1;

		newStartLine = parseBase10(buf, ptr.value + 1, ptr);
		if (buf[ptr.value] == ',')
			newLineCount = parseBase10(buf, ptr.value + 1, ptr);
		else
			newLineCount = 1;
	}

	int parseBody(Patch script, int end) {
		final byte[] buf = file.buf;
		int c = nextLF(buf, startOffset), last = c;

		old.nDeleted = 0;
		old.nAdded = 0;

		SCAN: for (; c < end; last = c, c = nextLF(buf, c)) {
			switch (buf[c]) {
			case ' ':
			case '\n':
				nContext++;
				continue;

			case '-':
				old.nDeleted++;
				continue;

			case '+':
				old.nAdded++;
				continue;

			case '\\': // Matches "\ No newline at end of file"
				continue;

			default:
				break SCAN;
			}
		}

		if (last < end && nContext + old.nDeleted - 1 == old.lineCount
				&& nContext + old.nAdded == newLineCount
				&& match(buf, last, Patch.SIG_FOOTER) >= 0) {
			// This is an extremely common occurrence of "corruption".
			// Users add footers with their signatures after this mark,
			// and git diff adds the git executable version number.
			// Let it slide; the hunk otherwise looked sound.
			//
			old.nDeleted--;
			return last;
		}

		if (nContext + old.nDeleted < old.lineCount) {
			final int missingCount = old.lineCount - (nContext + old.nDeleted);
			script.error(buf, startOffset, MessageFormat.format(
					JGitText.get().truncatedHunkOldLinesMissing,
					Integer.valueOf(missingCount)));

		} else if (nContext + old.nAdded < newLineCount) {
			final int missingCount = newLineCount - (nContext + old.nAdded);
			script.error(buf, startOffset, MessageFormat.format(
					JGitText.get().truncatedHunkNewLinesMissing,
					Integer.valueOf(missingCount)));

		} else if (nContext + old.nDeleted > old.lineCount
				|| nContext + old.nAdded > newLineCount) {
			final String oldcnt = old.lineCount + ":" + newLineCount; //$NON-NLS-1$
			final String newcnt = (nContext + old.nDeleted) + ":" //$NON-NLS-1$
					+ (nContext + old.nAdded);
			script.warn(buf, startOffset, MessageFormat.format(
					JGitText.get().hunkHeaderDoesNotMatchBodyLineCountOf, oldcnt, newcnt));
		}

		return c;
	}

	void extractFileLines(OutputStream[] out) throws IOException {
		final byte[] buf = file.buf;
		int ptr = startOffset;
		int eol = nextLF(buf, ptr);
		if (endOffset <= eol)
			return;

		// Treat the hunk header as though it were from the ancestor,
		// as it may have a function header appearing after it which
		// was copied out of the ancestor file.
		//
		out[0].write(buf, ptr, eol - ptr);

		SCAN: for (ptr = eol; ptr < endOffset; ptr = eol) {
			eol = nextLF(buf, ptr);
			switch (buf[ptr]) {
			case ' ':
			case '\n':
			case '\\':
				out[0].write(buf, ptr, eol - ptr);
				out[1].write(buf, ptr, eol - ptr);
				break;
			case '-':
				out[0].write(buf, ptr, eol - ptr);
				break;
			case '+':
				out[1].write(buf, ptr, eol - ptr);
				break;
			default:
				break SCAN;
			}
		}
	}

	void extractFileLines(final StringBuilder sb, final String[] text,
			final int[] offsets) {
		final byte[] buf = file.buf;
		int ptr = startOffset;
		int eol = nextLF(buf, ptr);
		if (endOffset <= eol)
			return;
		copyLine(sb, text, offsets, 0);
		SCAN: for (ptr = eol; ptr < endOffset; ptr = eol) {
			eol = nextLF(buf, ptr);
			switch (buf[ptr]) {
			case ' ':
			case '\n':
			case '\\':
				copyLine(sb, text, offsets, 0);
				skipLine(text, offsets, 1);
				break;
			case '-':
				copyLine(sb, text, offsets, 0);
				break;
			case '+':
				copyLine(sb, text, offsets, 1);
				break;
			default:
				break SCAN;
			}
		}
	}

	void copyLine(final StringBuilder sb, final String[] text,
			final int[] offsets, final int fileIdx) {
		final String s = text[fileIdx];
		final int start = offsets[fileIdx];
		int end = s.indexOf('\n', start);
		if (end < 0)
			end = s.length();
		else
			end++;
		sb.append(s, start, end);
		offsets[fileIdx] = end;
	}

	void skipLine(final String[] text, final int[] offsets,
			final int fileIdx) {
		final String s = text[fileIdx];
		final int end = s.indexOf('\n', offsets[fileIdx]);
		offsets[fileIdx] = end < 0 ? s.length() : end + 1;
	}

	@SuppressWarnings("nls")
	@Override
	public String toString() {
		StringBuilder buf = new StringBuilder();
		buf.append("HunkHeader[");
		buf.append(getOldImage().getStartLine());
		buf.append(',');
		buf.append(getOldImage().getLineCount());
		buf.append("->");
		buf.append(getNewStartLine()).append(',').append(getNewLineCount());
		buf.append(']');
		return buf.toString();
	}
}
