/*
 * Copyright (C) the libgit2 contributors. All rights reserved.
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

#include "common.h"
#include "repository.h"
#include "merge_file.h"

#include "git2/repository.h"
#include "git2/object.h"
#include "git2/index.h"

#include "xdiff/xdiff.h"

#define GIT_MERGE_FILE_SIDE_EXISTS(X)	((X)->mode != 0)

GIT_INLINE(const char *) merge_file_best_path(
	const git_merge_file_input *ancestor,
	const git_merge_file_input *ours,
	const git_merge_file_input *theirs)
{
	if (!GIT_MERGE_FILE_SIDE_EXISTS(ancestor)) {
		if (strcmp(ours->path, theirs->path) == 0)
			return ours->path;

		return NULL;
	}

	if (strcmp(ancestor->path, ours->path) == 0)
		return theirs->path;
	else if(strcmp(ancestor->path, theirs->path) == 0)
		return ours->path;

	return NULL;
}

GIT_INLINE(int) merge_file_best_mode(
	const git_merge_file_input *ancestor,
	const git_merge_file_input *ours,
	const git_merge_file_input *theirs)
{
	/*
	 * If ancestor didn't exist and either ours or theirs is executable,
	 * assume executable.  Otherwise, if any mode changed from the ancestor,
	 * use that one.
	 */
	if (GIT_MERGE_FILE_SIDE_EXISTS(ancestor)) {
		if (ours->mode == GIT_FILEMODE_BLOB_EXECUTABLE ||
			theirs->mode == GIT_FILEMODE_BLOB_EXECUTABLE)
			return GIT_FILEMODE_BLOB_EXECUTABLE;

		return GIT_FILEMODE_BLOB;
	}

	if (ancestor->mode == ours->mode)
		return theirs->mode;
	else if(ancestor->mode == theirs->mode)
		return ours->mode;

	return 0;
}

int git_merge_file_input_from_index_entry(
	git_merge_file_input *input,
	git_repository *repo,
	const git_index_entry *entry)
{
	git_odb *odb = NULL;
	int error = 0;

	assert(input && repo && entry);

	if (entry->mode == 0)
		return 0;

	if ((error = git_repository_odb(&odb, repo)) < 0 ||
		(error = git_odb_read(&input->odb_object, odb, &entry->oid)) < 0)
		goto done;

	input->mode = entry->mode;
	input->path = git__strdup(entry->path);
	input->mmfile.size = git_odb_object_size(input->odb_object);
	input->mmfile.ptr = (char *)git_odb_object_data(input->odb_object);

	if (input->label == NULL)
		input->label = entry->path;

done:
	git_odb_free(odb);

	return error;
}

int git_merge_file_input_from_diff_file(
	git_merge_file_input *input,
	git_repository *repo,
	const git_diff_file *file)
{
	git_odb *odb = NULL;
	int error = 0;

	assert(input && repo && file);

	if (file->mode == 0)
		return 0;

	if ((error = git_repository_odb(&odb, repo)) < 0 ||
		(error = git_odb_read(&input->odb_object, odb, &file->oid)) < 0)
		goto done;

	input->mode = file->mode;
	input->path = git__strdup(file->path);
	input->mmfile.size = git_odb_object_size(input->odb_object);
	input->mmfile.ptr = (char *)git_odb_object_data(input->odb_object);

	if (input->label == NULL)
		input->label = file->path;

done:
	git_odb_free(odb);

	return error;
}

int git_merge_files(
	git_merge_file_result *out,
	git_merge_file_input *ancestor,
	git_merge_file_input *ours,
	git_merge_file_input *theirs,
	git_merge_automerge_flags flags)
{
	xmparam_t xmparam;
	mmbuffer_t mmbuffer;
	int xdl_result;
	int error = 0;

	assert(out && ancestor && ours && theirs);

	memset(out, 0x0, sizeof(git_merge_file_result));

	if (!GIT_MERGE_FILE_SIDE_EXISTS(ours) || !GIT_MERGE_FILE_SIDE_EXISTS(theirs))
		return 0;

	memset(&xmparam, 0x0, sizeof(xmparam_t));
	xmparam.ancestor = ancestor->label;
	xmparam.file1 = ours->label;
	xmparam.file2 = theirs->label;

	out->path = merge_file_best_path(ancestor, ours, theirs);
	out->mode = merge_file_best_mode(ancestor, ours, theirs);

	if (flags == GIT_MERGE_AUTOMERGE_FAVOR_OURS)
		xmparam.favor = XDL_MERGE_FAVOR_OURS;

	if (flags == GIT_MERGE_AUTOMERGE_FAVOR_THEIRS)
		xmparam.favor = XDL_MERGE_FAVOR_THEIRS;

	if ((xdl_result = xdl_merge(&ancestor->mmfile, &ours->mmfile,
		&theirs->mmfile, &xmparam, &mmbuffer)) < 0) {
		giterr_set(GITERR_MERGE, "Failed to merge files.");
		error = -1;
		goto done;
	}

	out->automergeable = (xdl_result == 0);
	out->data = (unsigned char *)mmbuffer.ptr;
	out->len = mmbuffer.size;

done:
	return error;
}
