/*
 * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com>
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.merge;

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

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;

	/**
	 * 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;
	}

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

	/**
	 * 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 -> 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);
				} 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 -> 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);
			} 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 (theirsEdit != END_EDIT || oursEdit != END_EDIT) {
			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) {
					result.add(1, oursBeginB + commonPrefix, oursEndB
							- commonSuffix,
							ConflictState.FIRST_CONFLICTING_RANGE);
					result.add(2, theirsBeginB + commonPrefix, theirsEndB
							- commonSuffix,
							ConflictState.NEXT_CONFLICTING_RANGE);
				}

				// 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);
	}
}
