/*
 * 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.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.merge.MergeChunk.ConflictState;

/**
 * A class to convert merge results into a Git conformant textual presentation
 */
public class MergeFormatter {
	/**
	 * Formats the results of a merge of {@link RawText} objects in a Git
	 * conformant way. This method also assumes that the {@link RawText} objects
	 * being merged are line oriented files which use LF as delimiter. This
	 * method will also use LF to separate chunks and conflict metadata,
	 * therefore it fits only to texts that are LF-separated lines.
	 *
	 * @param out
	 *            the outputstream where to write the textual presentation
	 * @param res
	 *            the merge result which should be presented
	 * @param seqName
	 *            When a conflict is reported each conflicting range will get a
	 *            name. This name is following the "<<<<<<< " or ">>>>>>> "
	 *            conflict markers. The names for the sequences are given in
	 *            this list
	 * @param charsetName
	 *            the name of the characterSet used when writing conflict
	 *            metadata
	 * @throws IOException
	 */
	public void formatMerge(OutputStream out, MergeResult res,
			List<String> seqName, String charsetName) throws IOException {
		String lastConflictingName = null; // is set to non-null whenever we are
		// in a conflict
		boolean threeWayMerge = (res.getSequences().size() == 3);
		for (MergeChunk chunk : res) {
			RawText seq = (RawText) res.getSequences().get(
					chunk.getSequenceIndex());
			if (lastConflictingName != null
					&& chunk.getConflictState() != ConflictState.NEXT_CONFLICTING_RANGE) {
				// found the end of an conflict
				out.write((">>>>>>> " + lastConflictingName + "\n").getBytes(charsetName));
				lastConflictingName = null;
			}
			if (chunk.getConflictState() == ConflictState.FIRST_CONFLICTING_RANGE) {
				// found the start of an conflict
				out.write(("<<<<<<< " + seqName.get(chunk.getSequenceIndex()) +
						"\n").getBytes(charsetName));
				lastConflictingName = seqName.get(chunk.getSequenceIndex());
			} else if (chunk.getConflictState() == ConflictState.NEXT_CONFLICTING_RANGE) {
				// found another conflicting chunk

				/*
				 * In case of a non-three-way merge I'll add the name of the
				 * conflicting chunk behind the equal signs. I also append the
				 * name of the last conflicting chunk after the ending
				 * greater-than signs. If somebody knows a better notation to
				 * present non-three-way merges - feel free to correct here.
				 */
				lastConflictingName = seqName.get(chunk.getSequenceIndex());
				out.write((threeWayMerge ? "=======\n" : "======= "
						+ lastConflictingName + "\n").getBytes(charsetName));
			}
			// the lines with conflict-metadata are written. Now write the chunk
			for (int i = chunk.getBegin(); i < chunk.getEnd(); i++) {
				seq.writeLine(out, i);
				out.write('\n');
			}
		}
		// one possible leftover: if the merge result ended with a conflict we
		// have to close the last conflict here
		if (lastConflictingName != null) {
			out.write((">>>>>>> " + lastConflictingName + "\n").getBytes(charsetName));
		}
	}

	/**
	 * Formats the results of a merge of exactly two {@link RawText} objects in
	 * a Git conformant way. This convenience method accepts the names for the
	 * three sequences (base and the two merged sequences) as explicit
	 * parameters and doesn't require the caller to specify a List
	 *
	 * @param out
	 *            the {@link OutputStream} where to write the textual
	 *            presentation
	 * @param res
	 *            the merge result which should be presented
	 * @param baseName
	 *            the name ranges from the base should get
	 * @param oursName
	 *            the name ranges from ours should get
	 * @param theirsName
	 *            the name ranges from theirs should get
	 * @param charsetName
	 *            the name of the characterSet used when writing conflict
	 *            metadata
	 * @throws IOException
	 */
	public void formatMerge(OutputStream out, MergeResult res, String baseName,
			String oursName, String theirsName, String charsetName) throws IOException {
		List<String> names = new ArrayList<String>(3);
		names.add(baseName);
		names.add(oursName);
		names.add(theirsName);
		formatMerge(out, res, names, charsetName);
	}
}
