/*
 *  LibXDiff by Davide Libenzi ( File Differential Library )
 *  Copyright (C) 2003-2006 Davide Libenzi, Johannes E. Schindelin
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  Davide Libenzi <davidel@xmailserver.org>
 *
 */

#include "xinclude.h"

typedef struct s_xdmerge {
	struct s_xdmerge *next;
	/*
	 * 0 = conflict,
	 * 1 = no conflict, take first,
	 * 2 = no conflict, take second.
	 */
	int mode;
	long i1, i2;
	long chg1, chg2;
} xdmerge_t;

static int xdl_append_merge(xdmerge_t **merge, int mode,
		long i1, long chg1, long i2, long chg2)
{
	xdmerge_t *m = *merge;
	if (m && (i1 <= m->i1 + m->chg1 || i2 <= m->i2 + m->chg2)) {
		if (mode != m->mode)
			m->mode = 0;
		m->chg1 = i1 + chg1 - m->i1;
		m->chg2 = i2 + chg2 - m->i2;
	} else {
		m = xdl_malloc(sizeof(xdmerge_t));
		if (!m)
			return -1;
		m->next = NULL;
		m->mode = mode;
		m->i1 = i1;
		m->chg1 = chg1;
		m->i2 = i2;
		m->chg2 = chg2;
		if (*merge)
			(*merge)->next = m;
		*merge = m;
	}
	return 0;
}

static int xdl_cleanup_merge(xdmerge_t *c)
{
	int count = 0;
	xdmerge_t *next_c;

	/* were there conflicts? */
	for (; c; c = next_c) {
		if (c->mode == 0)
			count++;
		next_c = c->next;
		free(c);
	}
	return count;
}

static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
		int line_count, long flags)
{
	int i;
	xrecord_t **rec1 = xe1->xdf2.recs + i1;
	xrecord_t **rec2 = xe2->xdf2.recs + i2;

	for (i = 0; i < line_count; i++) {
		int result = xdl_recmatch(rec1[i]->ptr, rec1[i]->size,
			rec2[i]->ptr, rec2[i]->size, flags);
		if (!result)
			return -1;
	}
	return 0;
}

static int xdl_recs_copy(xdfenv_t *xe, int i, int count, int add_nl, char *dest)
{
	xrecord_t **recs = xe->xdf2.recs + i;
	int size = 0;

	if (count < 1)
		return 0;

	for (i = 0; i < count; size += recs[i++]->size)
		if (dest)
			memcpy(dest + size, recs[i]->ptr, recs[i]->size);
	if (add_nl) {
		i = recs[count - 1]->size;
		if (i == 0 || recs[count - 1]->ptr[i - 1] != '\n') {
			if (dest)
				dest[size] = '\n';
			size++;
		}
	}
	return size;
}

static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
		xdfenv_t *xe2, const char *name2, xdmerge_t *m, char *dest)
{
	const int marker_size = 7;
	int marker1_size = (name1 ? strlen(name1) + 1 : 0);
	int marker2_size = (name2 ? strlen(name2) + 1 : 0);
	int conflict_marker_size = 3 * (marker_size + 1)
		+ marker1_size + marker2_size;
	int size, i1, j;

	for (size = i1 = 0; m; m = m->next) {
		if (m->mode == 0) {
			size += xdl_recs_copy(xe1, i1, m->i1 - i1, 0,
					dest ? dest + size : NULL);
			if (dest) {
				for (j = 0; j < marker_size; j++)
					dest[size++] = '<';
				if (marker1_size) {
					dest[size] = ' ';
					memcpy(dest + size + 1, name1,
							marker1_size - 1);
					size += marker1_size;
				}
				dest[size++] = '\n';
			} else
				size += conflict_marker_size;
			size += xdl_recs_copy(xe1, m->i1, m->chg1, 1,
					dest ? dest + size : NULL);
			if (dest) {
				for (j = 0; j < marker_size; j++)
					dest[size++] = '=';
				dest[size++] = '\n';
			}
			size += xdl_recs_copy(xe2, m->i2, m->chg2, 1,
					dest ? dest + size : NULL);
			if (dest) {
				for (j = 0; j < marker_size; j++)
					dest[size++] = '>';
				if (marker2_size) {
					dest[size] = ' ';
					memcpy(dest + size + 1, name2,
							marker2_size - 1);
					size += marker2_size;
				}
				dest[size++] = '\n';
			}
		} else if (m->mode == 1)
			size += xdl_recs_copy(xe1, i1, m->i1 + m->chg1 - i1, 0,
					dest ? dest + size : NULL);
		else if (m->mode == 2)
			size += xdl_recs_copy(xe2, m->i2 - m->i1 + i1,
					m->i1 + m->chg2 - i1, 0,
					dest ? dest + size : NULL);
		else
			continue;
		i1 = m->i1 + m->chg1;
	}
	size += xdl_recs_copy(xe1, i1, xe1->xdf2.nrec - i1, 0,
			dest ? dest + size : NULL);
	return size;
}

/*
 * Sometimes, changes are not quite identical, but differ in only a few
 * lines. Try hard to show only these few lines as conflicting.
 */
static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
		xpparam_t const *xpp)
{
	for (; m; m = m->next) {
		mmfile_t t1, t2;
		xdfenv_t xe;
		xdchange_t *xscr, *x;
		int i1 = m->i1, i2 = m->i2;

		/* let's handle just the conflicts */
		if (m->mode)
			continue;

		/* no sense refining a conflict when one side is empty */
		if (m->chg1 == 0 || m->chg2 == 0)
			continue;

		/*
		 * This probably does not work outside git, since
		 * we have a very simple mmfile structure.
		 */
		t1.ptr = (char *)xe1->xdf2.recs[m->i1]->ptr;
		t1.size = xe1->xdf2.recs[m->i1 + m->chg1 - 1]->ptr
			+ xe1->xdf2.recs[m->i1 + m->chg1 - 1]->size - t1.ptr;
		t2.ptr = (char *)xe2->xdf2.recs[m->i2]->ptr;
		t2.size = xe2->xdf2.recs[m->i2 + m->chg2 - 1]->ptr
			+ xe2->xdf2.recs[m->i2 + m->chg2 - 1]->size - t2.ptr;
		if (xdl_do_diff(&t1, &t2, xpp, &xe) < 0)
			return -1;
		if (xdl_change_compact(&xe.xdf1, &xe.xdf2, xpp->flags) < 0 ||
		    xdl_change_compact(&xe.xdf2, &xe.xdf1, xpp->flags) < 0 ||
		    xdl_build_script(&xe, &xscr) < 0) {
			xdl_free_env(&xe);
			return -1;
		}
		if (!xscr) {
			/* If this happens, the changes are identical. */
			xdl_free_env(&xe);
			m->mode = 4;
			continue;
		}
		x = xscr;
		m->i1 = xscr->i1 + i1;
		m->chg1 = xscr->chg1;
		m->i2 = xscr->i2 + i2;
		m->chg2 = xscr->chg2;
		while (xscr->next) {
			xdmerge_t *m2 = xdl_malloc(sizeof(xdmerge_t));
			if (!m2) {
				xdl_free_env(&xe);
				xdl_free_script(x);
				return -1;
			}
			xscr = xscr->next;
			m2->next = m->next;
			m->next = m2;
			m = m2;
			m->mode = 0;
			m->i1 = xscr->i1 + i1;
			m->chg1 = xscr->chg1;
			m->i2 = xscr->i2 + i2;
			m->chg2 = xscr->chg2;
		}
		xdl_free_env(&xe);
		xdl_free_script(x);
	}
	return 0;
}

static int line_contains_alnum(const char *ptr, long size)
{
	while (size--)
		if (isalnum(*(ptr++)))
			return 1;
	return 0;
}

static int lines_contain_alnum(xdfenv_t *xe, int i, int chg)
{
	for (; chg; chg--, i++)
		if (line_contains_alnum(xe->xdf2.recs[i]->ptr,
				xe->xdf2.recs[i]->size))
			return 1;
	return 0;
}

/*
 * This function merges m and m->next, marking everything between those hunks
 * as conflicting, too.
 */
static void xdl_merge_two_conflicts(xdmerge_t *m)
{
	xdmerge_t *next_m = m->next;
	m->chg1 = next_m->i1 + next_m->chg1 - m->i1;
	m->chg2 = next_m->i2 + next_m->chg2 - m->i2;
	m->next = next_m->next;
	free(next_m);
}

/*
 * If there are less than 3 non-conflicting lines between conflicts,
 * it appears simpler -- because it takes up less (or as many) lines --
 * if the lines are moved into the conflicts.
 */
static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
				      int simplify_if_no_alnum)
{
	int result = 0;

	if (!m)
		return result;
	for (;;) {
		xdmerge_t *next_m = m->next;
		int begin, end;

		if (!next_m)
			return result;

		begin = m->i1 + m->chg1;
		end = next_m->i1;

		if (m->mode != 0 || next_m->mode != 0 ||
		    (end - begin > 3 &&
		     (!simplify_if_no_alnum ||
		      lines_contain_alnum(xe1, begin, end - begin)))) {
			m = next_m;
		} else {
			result++;
			xdl_merge_two_conflicts(m);
		}
	}
}

/*
 * level == 0: mark all overlapping changes as conflict
 * level == 1: mark overlapping changes as conflict only if not identical
 * level == 2: analyze non-identical changes for minimal conflict set
 * level == 3: analyze non-identical changes for minimal conflict set, but
 *             treat hunks not containing any letter or number as conflicting
 *
 * returns < 0 on error, == 0 for no conflicts, else number of conflicts
 */
static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
		xdfenv_t *xe2, xdchange_t *xscr2, const char *name2,
		int level, xpparam_t const *xpp, mmbuffer_t *result) {
	xdmerge_t *changes, *c;
	int i1, i2, chg1, chg2;

	c = changes = NULL;

	while (xscr1 && xscr2) {
		if (!changes)
			changes = c;
		if (xscr1->i1 + xscr1->chg1 < xscr2->i1) {
			i1 = xscr1->i2;
			i2 = xscr2->i2 - xscr2->i1 + xscr1->i1;
			chg1 = xscr1->chg2;
			chg2 = xscr1->chg1;
			if (xdl_append_merge(&c, 1, i1, chg1, i2, chg2)) {
				xdl_cleanup_merge(changes);
				return -1;
			}
			xscr1 = xscr1->next;
			continue;
		}
		if (xscr2->i1 + xscr2->chg1 < xscr1->i1) {
			i1 = xscr1->i2 - xscr1->i1 + xscr2->i1;
			i2 = xscr2->i2;
			chg1 = xscr2->chg1;
			chg2 = xscr2->chg2;
			if (xdl_append_merge(&c, 2, i1, chg1, i2, chg2)) {
				xdl_cleanup_merge(changes);
				return -1;
			}
			xscr2 = xscr2->next;
			continue;
		}
		if (level < 1 || xscr1->i1 != xscr2->i1 ||
				xscr1->chg1 != xscr2->chg1 ||
				xscr1->chg2 != xscr2->chg2 ||
				xdl_merge_cmp_lines(xe1, xscr1->i2,
					xe2, xscr2->i2,
					xscr1->chg2, xpp->flags)) {
			/* conflict */
			int off = xscr1->i1 - xscr2->i1;
			int ffo = off + xscr1->chg1 - xscr2->chg1;

			i1 = xscr1->i2;
			i2 = xscr2->i2;
			if (off > 0)
				i1 -= off;
			else
				i2 += off;
			chg1 = xscr1->i2 + xscr1->chg2 - i1;
			chg2 = xscr2->i2 + xscr2->chg2 - i2;
			if (ffo > 0)
				chg2 += ffo;
			else
				chg1 -= ffo;
			if (xdl_append_merge(&c, 0, i1, chg1, i2, chg2)) {
				xdl_cleanup_merge(changes);
				return -1;
			}
		}

		i1 = xscr1->i1 + xscr1->chg1;
		i2 = xscr2->i1 + xscr2->chg1;

		if (i1 >= i2)
			xscr2 = xscr2->next;
		if (i2 >= i1)
			xscr1 = xscr1->next;
	}
	while (xscr1) {
		if (!changes)
			changes = c;
		i1 = xscr1->i2;
		i2 = xscr1->i1 + xe2->xdf2.nrec - xe2->xdf1.nrec;
		chg1 = xscr1->chg2;
		chg2 = xscr1->chg1;
		if (xdl_append_merge(&c, 1, i1, chg1, i2, chg2)) {
			xdl_cleanup_merge(changes);
			return -1;
		}
		xscr1 = xscr1->next;
	}
	while (xscr2) {
		if (!changes)
			changes = c;
		i1 = xscr2->i1 + xe1->xdf2.nrec - xe1->xdf1.nrec;
		i2 = xscr2->i2;
		chg1 = xscr2->chg1;
		chg2 = xscr2->chg2;
		if (xdl_append_merge(&c, 2, i1, chg1, i2, chg2)) {
			xdl_cleanup_merge(changes);
			return -1;
		}
		xscr2 = xscr2->next;
	}
	if (!changes)
		changes = c;
	/* refine conflicts */
	if (level > 1 &&
	    (xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
	     xdl_simplify_non_conflicts(xe1, changes, level > 2) < 0)) {
		xdl_cleanup_merge(changes);
		return -1;
	}
	/* output */
	if (result) {
		int size = xdl_fill_merge_buffer(xe1, name1, xe2, name2,
			changes, NULL);
		result->ptr = xdl_malloc(size);
		if (!result->ptr) {
			xdl_cleanup_merge(changes);
			return -1;
		}
		result->size = size;
		xdl_fill_merge_buffer(xe1, name1, xe2, name2, changes,
				result->ptr);
	}
	return xdl_cleanup_merge(changes);
}

int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
		mmfile_t *mf2, const char *name2,
		xpparam_t const *xpp, int level, mmbuffer_t *result) {
	xdchange_t *xscr1, *xscr2;
	xdfenv_t xe1, xe2;
	int status;

	result->ptr = NULL;
	result->size = 0;

	if (xdl_do_diff(orig, mf1, xpp, &xe1) < 0 ||
			xdl_do_diff(orig, mf2, xpp, &xe2) < 0) {
		return -1;
	}
	if (xdl_change_compact(&xe1.xdf1, &xe1.xdf2, xpp->flags) < 0 ||
	    xdl_change_compact(&xe1.xdf2, &xe1.xdf1, xpp->flags) < 0 ||
	    xdl_build_script(&xe1, &xscr1) < 0) {
		xdl_free_env(&xe1);
		return -1;
	}
	if (xdl_change_compact(&xe2.xdf1, &xe2.xdf2, xpp->flags) < 0 ||
	    xdl_change_compact(&xe2.xdf2, &xe2.xdf1, xpp->flags) < 0 ||
	    xdl_build_script(&xe2, &xscr2) < 0) {
		xdl_free_env(&xe2);
		return -1;
	}
	status = 0;
	if (xscr1 || xscr2) {
		if (!xscr1) {
			result->ptr = xdl_malloc(mf2->size);
			memcpy(result->ptr, mf2->ptr, mf2->size);
			result->size = mf2->size;
		} else if (!xscr2) {
			result->ptr = xdl_malloc(mf1->size);
			memcpy(result->ptr, mf1->ptr, mf1->size);
			result->size = mf1->size;
		} else {
			status = xdl_do_merge(&xe1, xscr1, name1,
					      &xe2, xscr2, name2,
					      level, xpp, result);
		}
		xdl_free_script(xscr1);
		xdl_free_script(xscr2);
	}
	xdl_free_env(&xe1);
	xdl_free_env(&xe2);

	return status;
}
