/*
 * Copyright (C) 2008, 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.lib.Constants.encodeASCII;
import static org.eclipse.jgit.util.RawParseUtils.match;
import static org.eclipse.jgit.util.RawParseUtils.nextLF;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.FileMode;

/**
 * A file in the Git "diff --cc" or "diff --combined" format.
 * <p>
 * A combined diff shows an n-way comparison between two or more ancestors and
 * the final revision. Its primary function is to perform code reviews on a
 * merge which introduces changes not in any ancestor.
 */
public class CombinedFileHeader extends FileHeader {
	private static final byte[] MODE = encodeASCII("mode "); //$NON-NLS-1$

	private AbbreviatedObjectId[] oldIds;

	private FileMode[] oldModes;

	CombinedFileHeader(byte[] b, int offset) {
		super(b, offset);
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<? extends CombinedHunkHeader> getHunks() {
		return (List<CombinedHunkHeader>) super.getHunks();
	}

	/**
	 * @return number of ancestor revisions mentioned in this diff.
	 */
	@Override
	public int getParentCount() {
		return oldIds.length;
	}

	/**
	 * {@inheritDoc}
	 *
	 * @return get the file mode of the first parent.
	 */
	@Override
	public FileMode getOldMode() {
		return getOldMode(0);
	}

	/**
	 * Get the file mode of the nth ancestor
	 *
	 * @param nthParent
	 *            the ancestor to get the mode of
	 * @return the mode of the requested ancestor.
	 */
	public FileMode getOldMode(int nthParent) {
		return oldModes[nthParent];
	}

	/**
	 * {@inheritDoc}
	 *
	 * @return get the object id of the first parent.
	 */
	@Override
	public AbbreviatedObjectId getOldId() {
		return getOldId(0);
	}

	/**
	 * Get the ObjectId of the nth ancestor
	 *
	 * @param nthParent
	 *            the ancestor to get the object id of
	 * @return the id of the requested ancestor.
	 */
	public AbbreviatedObjectId getOldId(int nthParent) {
		return oldIds[nthParent];
	}

	@Override
	public String getScriptText(Charset ocs, Charset ncs) {
		final Charset[] cs = new Charset[getParentCount() + 1];
		Arrays.fill(cs, ocs);
		cs[getParentCount()] = ncs;
		return getScriptText(cs);
	}

	@Override
	public String getScriptText(Charset[] charsetGuess) {
		return super.getScriptText(charsetGuess);
	}

	@Override
	int parseGitHeaders(int ptr, int end) {
		while (ptr < end) {
			final int eol = nextLF(buf, ptr);
			if (isHunkHdr(buf, ptr, end) >= 1) {
				// First hunk header; break out and parse them later.
				break;

			} else if (match(buf, ptr, OLD_NAME) >= 0) {
				parseOldName(ptr, eol);

			} else if (match(buf, ptr, NEW_NAME) >= 0) {
				parseNewName(ptr, eol);

			} else if (match(buf, ptr, INDEX) >= 0) {
				parseIndexLine(ptr + INDEX.length, eol);

			} else if (match(buf, ptr, MODE) >= 0) {
				parseModeLine(ptr + MODE.length, eol);

			} else if (match(buf, ptr, NEW_FILE_MODE) >= 0) {
				parseNewFileMode(ptr, eol);

			} else if (match(buf, ptr, DELETED_FILE_MODE) >= 0) {
				parseDeletedFileMode(ptr + DELETED_FILE_MODE.length, eol);

			} else {
				// Probably an empty patch (stat dirty).
				break;
			}

			ptr = eol;
		}
		return ptr;
	}

	@Override
	protected void parseIndexLine(int ptr, int eol) {
		// "index $asha1,$bsha1..$csha1"
		//
		final List<AbbreviatedObjectId> ids = new ArrayList<>();
		while (ptr < eol) {
			final int comma = nextLF(buf, ptr, ',');
			if (eol <= comma)
				break;
			ids.add(AbbreviatedObjectId.fromString(buf, ptr, comma - 1));
			ptr = comma;
		}

		oldIds = new AbbreviatedObjectId[ids.size() + 1];
		ids.toArray(oldIds);
		final int dot2 = nextLF(buf, ptr, '.');
		oldIds[ids.size()] = AbbreviatedObjectId.fromString(buf, ptr, dot2 - 1);
		newId = AbbreviatedObjectId.fromString(buf, dot2 + 1, eol - 1);
		oldModes = new FileMode[oldIds.length];
	}

	@Override
	protected void parseNewFileMode(int ptr, int eol) {
		for (int i = 0; i < oldModes.length; i++)
			oldModes[i] = FileMode.MISSING;
		super.parseNewFileMode(ptr, eol);
	}

	@Override
	HunkHeader newHunkHeader(int offset) {
		return new CombinedHunkHeader(this, offset);
	}

	private void parseModeLine(int ptr, int eol) {
		// "mode $amode,$bmode..$cmode"
		//
		int n = 0;
		while (ptr < eol) {
			final int comma = nextLF(buf, ptr, ',');
			if (eol <= comma)
				break;
			oldModes[n++] = parseFileMode(ptr, comma);
			ptr = comma;
		}
		final int dot2 = nextLF(buf, ptr, '.');
		oldModes[n] = parseFileMode(ptr, dot2);
		newMode = parseFileMode(dot2 + 1, eol);
	}

	private void parseDeletedFileMode(int ptr, int eol) {
		// "deleted file mode $amode,$bmode"
		//
		changeType = ChangeType.DELETE;
		int n = 0;
		while (ptr < eol) {
			final int comma = nextLF(buf, ptr, ',');
			if (eol <= comma)
				break;
			oldModes[n++] = parseFileMode(ptr, comma);
			ptr = comma;
		}
		oldModes[n] = parseFileMode(ptr, eol);
		newMode = FileMode.MISSING;
	}
}
