/*
 * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com> 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.merge;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.diff.DiffAlgorithm;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.HistogramDiff;
import org.eclipse.jgit.diff.Sequence;
import org.eclipse.jgit.diff.SequenceComparator;
import org.eclipse.jgit.merge.MergeChunk.ConflictState;

/**
 * Provides the merge algorithm which does a three-way merge on content provided
 * as RawText. By default {@link org.eclipse.jgit.diff.HistogramDiff} is used as
 * diff algorithm.
 */
public final class MergeAlgorithm {

	private final DiffAlgorithm diffAlg;

	@NonNull
	private ContentMergeStrategy strategy = ContentMergeStrategy.CONFLICT;

	/**
	 * Creates a new MergeAlgorithm which uses
	 * {@link org.eclipse.jgit.diff.HistogramDiff} as diff algorithm
	 */
	public MergeAlgorithm() {
		this(new HistogramDiff());
	}

	/**
	 * Creates a new MergeAlgorithm
	 *
	 * @param diff
	 *            the diff algorithm used by this merge
	 */
	public MergeAlgorithm(DiffAlgorithm diff) {
		this.diffAlg = diff;
	}

	/**
	 * Retrieves the {@link ContentMergeStrategy}.
	 *
	 * @return the {@link ContentMergeStrategy} in effect
	 * @since 5.12
	 */
	@NonNull
	public ContentMergeStrategy getContentMergeStrategy() {
		return strategy;
	}

	/**
	 * Sets the {@link ContentMergeStrategy}.
	 *
	 * @param strategy
	 *            {@link ContentMergeStrategy} to set; if {@code null}, set
	 *            {@link ContentMergeStrategy#CONFLICT}
	 * @since 5.12
	 */
	public void setContentMergeStrategy(ContentMergeStrategy strategy) {
		this.strategy = strategy == null ? ContentMergeStrategy.CONFLICT
				: strategy;
	}

	// An special edit which acts as a sentinel value by marking the end the
	// list of edits
	private static final Edit END_EDIT = new Edit(Integer.MAX_VALUE,
			Integer.MAX_VALUE);

	@SuppressWarnings("ReferenceEquality")
	private static boolean isEndEdit(Edit edit) {
		return edit == END_EDIT;
	}

	/**
	 * Does the three way merge between a common base and two sequences.
	 *
	 * @param cmp comparison method for this execution.
	 * @param base the common base sequence
	 * @param ours the first sequence to be merged
	 * @param theirs the second sequence to be merged
	 * @return the resulting content
	 */
	public <S extends Sequence> MergeResult<S> merge(
			SequenceComparator<S> cmp, S base, S ours, S theirs) {
		List<S> sequences = new ArrayList<>(3);
		sequences.add(base);
		sequences.add(ours);
		sequences.add(theirs);
		MergeResult<S> result = new MergeResult<>(sequences);

		if (ours.size() == 0) {
			if (theirs.size() != 0) {
				EditList theirsEdits = diffAlg.diff(cmp, base, theirs);
				if (!theirsEdits.isEmpty()) {
					// we deleted, they modified
					switch (strategy) {
					case OURS:
						result.add(1, 0, 0, ConflictState.NO_CONFLICT);
						break;
					case THEIRS:
						result.add(2, 0, theirs.size(),
								ConflictState.NO_CONFLICT);
						break;
					default:
						// Let their complete content conflict with empty text
						result.add(1, 0, 0,
								ConflictState.FIRST_CONFLICTING_RANGE);
						result.add(2, 0, theirs.size(),
								ConflictState.NEXT_CONFLICTING_RANGE);
						break;
					}
				} else {
					// we deleted, they didn't modify -> Let our deletion win
					result.add(1, 0, 0, ConflictState.NO_CONFLICT);
				}
			} else {
				// we and they deleted -> return a single chunk of nothing
				result.add(1, 0, 0, ConflictState.NO_CONFLICT);
			}
			return result;
		} else if (theirs.size() == 0) {
			EditList oursEdits = diffAlg.diff(cmp, base, ours);
			if (!oursEdits.isEmpty()) {
				// we modified, they deleted
				switch (strategy) {
				case OURS:
					result.add(1, 0, ours.size(), ConflictState.NO_CONFLICT);
					break;
				case THEIRS:
					result.add(2, 0, 0, ConflictState.NO_CONFLICT);
					break;
				default:
					// Let our complete content conflict with empty text
					result.add(1, 0, ours.size(),
							ConflictState.FIRST_CONFLICTING_RANGE);
					result.add(2, 0, 0, ConflictState.NEXT_CONFLICTING_RANGE);
					break;
				}
			} else {
				// they deleted, we didn't modify -> Let their deletion win
				result.add(2, 0, 0, ConflictState.NO_CONFLICT);
			}
			return result;
		}

		EditList oursEdits = diffAlg.diff(cmp, base, ours);
		Iterator<Edit> baseToOurs = oursEdits.iterator();
		EditList theirsEdits = diffAlg.diff(cmp, base, theirs);
		Iterator<Edit> baseToTheirs = theirsEdits.iterator();
		int current = 0; // points to the next line (first line is 0) of base
		                 // which was not handled yet
		Edit oursEdit = nextEdit(baseToOurs);
		Edit theirsEdit = nextEdit(baseToTheirs);

		// iterate over all edits from base to ours and from base to theirs
		// leave the loop when there are no edits more for ours or for theirs
		// (or both)
		while (!isEndEdit(theirsEdit) || !isEndEdit(oursEdit)) {
			if (oursEdit.getEndA() < theirsEdit.getBeginA()) {
				// something was changed in ours not overlapping with any change
				// from theirs. First add the common part in front of the edit
				// then the edit.
				if (current != oursEdit.getBeginA()) {
					result.add(0, current, oursEdit.getBeginA(),
							ConflictState.NO_CONFLICT);
				}
				result.add(1, oursEdit.getBeginB(), oursEdit.getEndB(),
						ConflictState.NO_CONFLICT);
				current = oursEdit.getEndA();
				oursEdit = nextEdit(baseToOurs);
			} else if (theirsEdit.getEndA() < oursEdit.getBeginA()) {
				// something was changed in theirs not overlapping with any
				// from ours. First add the common part in front of the edit
				// then the edit.
				if (current != theirsEdit.getBeginA()) {
					result.add(0, current, theirsEdit.getBeginA(),
							ConflictState.NO_CONFLICT);
				}
				result.add(2, theirsEdit.getBeginB(), theirsEdit.getEndB(),
						ConflictState.NO_CONFLICT);
				current = theirsEdit.getEndA();
				theirsEdit = nextEdit(baseToTheirs);
			} else {
				// here we found a real overlapping modification

				// if there is a common part in front of the conflict add it
				if (oursEdit.getBeginA() != current
						&& theirsEdit.getBeginA() != current) {
					result.add(0, current, Math.min(oursEdit.getBeginA(),
							theirsEdit.getBeginA()), ConflictState.NO_CONFLICT);
				}

				// set some initial values for the ranges in A and B which we
				// want to handle
				int oursBeginB = oursEdit.getBeginB();
				int theirsBeginB = theirsEdit.getBeginB();
				// harmonize the start of the ranges in A and B
				if (oursEdit.getBeginA() < theirsEdit.getBeginA()) {
					theirsBeginB -= theirsEdit.getBeginA()
							- oursEdit.getBeginA();
				} else {
					oursBeginB -= oursEdit.getBeginA() - theirsEdit.getBeginA();
				}

				// combine edits:
				// Maybe an Edit on one side corresponds to multiple Edits on
				// the other side. Then we have to combine the Edits of the
				// other side - so in the end we can merge together two single
				// edits.
				//
				// It is important to notice that this combining will extend the
				// ranges of our conflict always downwards (towards the end of
				// the content). The starts of the conflicting ranges in ours
				// and theirs are not touched here.
				//
				// This combining is an iterative process: after we have
				// combined some edits we have to do the check again. The
				// combined edits could now correspond to multiple edits on the
				// other side.
				//
				// Example: when this combining algorithm works on the following
				// edits
				// oursEdits=((0-5,0-5),(6-8,6-8),(10-11,10-11)) and
				// theirsEdits=((0-1,0-1),(2-3,2-3),(5-7,5-7))
				// it will merge them into
				// oursEdits=((0-8,0-8),(10-11,10-11)) and
				// theirsEdits=((0-7,0-7))
				//
				// Since the only interesting thing to us is how in ours and
				// theirs the end of the conflicting range is changing we let
				// oursEdit and theirsEdit point to the last conflicting edit
				Edit nextOursEdit = nextEdit(baseToOurs);
				Edit nextTheirsEdit = nextEdit(baseToTheirs);
				for (;;) {
					if (oursEdit.getEndA() >= nextTheirsEdit.getBeginA()) {
						theirsEdit = nextTheirsEdit;
						nextTheirsEdit = nextEdit(baseToTheirs);
					} else if (theirsEdit.getEndA() >= nextOursEdit.getBeginA()) {
						oursEdit = nextOursEdit;
						nextOursEdit = nextEdit(baseToOurs);
					} else {
						break;
					}
				}

				// harmonize the end of the ranges in A and B
				int oursEndB = oursEdit.getEndB();
				int theirsEndB = theirsEdit.getEndB();
				if (oursEdit.getEndA() < theirsEdit.getEndA()) {
					oursEndB += theirsEdit.getEndA() - oursEdit.getEndA();
				} else {
					theirsEndB += oursEdit.getEndA() - theirsEdit.getEndA();
				}

				// A conflicting region is found. Strip off common lines in
				// in the beginning and the end of the conflicting region

				// Determine the minimum length of the conflicting areas in OURS
				// and THEIRS. Also determine how much bigger the conflicting
				// area in THEIRS is compared to OURS. All that is needed to
				// limit the search for common areas at the beginning or end
				// (the common areas cannot be bigger then the smaller
				// conflicting area. The delta is needed to know whether the
				// complete conflicting area is common in OURS and THEIRS.
				int minBSize = oursEndB - oursBeginB;
				int BSizeDelta = minBSize - (theirsEndB - theirsBeginB);
				if (BSizeDelta > 0)
					minBSize -= BSizeDelta;

				int commonPrefix = 0;
				while (commonPrefix < minBSize
						&& cmp.equals(ours, oursBeginB + commonPrefix, theirs,
								theirsBeginB + commonPrefix))
					commonPrefix++;
				minBSize -= commonPrefix;
				int commonSuffix = 0;
				while (commonSuffix < minBSize
						&& cmp.equals(ours, oursEndB - commonSuffix - 1, theirs,
								theirsEndB - commonSuffix - 1))
					commonSuffix++;
				minBSize -= commonSuffix;

				// Add the common lines at start of conflict
				if (commonPrefix > 0)
					result.add(1, oursBeginB, oursBeginB + commonPrefix,
							ConflictState.NO_CONFLICT);

				// Add the conflict (Only if there is a conflict left to report)
				if (minBSize > 0 || BSizeDelta != 0) {
					switch (strategy) {
					case OURS:
						result.add(1, oursBeginB + commonPrefix,
								oursEndB - commonSuffix,
								ConflictState.NO_CONFLICT);
						break;
					case THEIRS:
						result.add(2, theirsBeginB + commonPrefix,
								theirsEndB - commonSuffix,
								ConflictState.NO_CONFLICT);
						break;
					default:
						result.add(1, oursBeginB + commonPrefix,
								oursEndB - commonSuffix,
								ConflictState.FIRST_CONFLICTING_RANGE);
						result.add(2, theirsBeginB + commonPrefix,
								theirsEndB - commonSuffix,
								ConflictState.NEXT_CONFLICTING_RANGE);
						break;
					}
				}

				// Add the common lines at end of conflict
				if (commonSuffix > 0)
					result.add(1, oursEndB - commonSuffix, oursEndB,
							ConflictState.NO_CONFLICT);

				current = Math.max(oursEdit.getEndA(), theirsEdit.getEndA());
				oursEdit = nextOursEdit;
				theirsEdit = nextTheirsEdit;
			}
		}
		// maybe we have a common part behind the last edit: copy it to the
		// result
		if (current < base.size()) {
			result.add(0, current, base.size(), ConflictState.NO_CONFLICT);
		}
		return result;
	}

	/**
	 * Helper method which returns the next Edit for an Iterator over Edits.
	 * When there are no more edits left this method will return the constant
	 * END_EDIT.
	 *
	 * @param it
	 *            the iterator for which the next edit should be returned
	 * @return the next edit from the iterator or END_EDIT if there no more
	 *         edits
	 */
	private static Edit nextEdit(Iterator<Edit> it) {
		return (it.hasNext() ? it.next() : END_EDIT);
	}
}
