/*
 * 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 "git2.h"
#include "fileops.h"
#include "hash.h"
#include "vector.h"
#include "tree.h"
#include "status.h"
#include "git2/status.h"
#include "repository.h"
#include "ignore.h"
#include "index.h"

#include "git2/diff.h"
#include "diff.h"
#include "diff_generate.h"

static unsigned int index_delta2status(const git_diff_delta *head2idx)
{
	git_status_t st = GIT_STATUS_CURRENT;

	switch (head2idx->status) {
	case GIT_DELTA_ADDED:
	case GIT_DELTA_COPIED:
		st = GIT_STATUS_INDEX_NEW;
		break;
	case GIT_DELTA_DELETED:
		st = GIT_STATUS_INDEX_DELETED;
		break;
	case GIT_DELTA_MODIFIED:
		st = GIT_STATUS_INDEX_MODIFIED;
		break;
	case GIT_DELTA_RENAMED:
		st = GIT_STATUS_INDEX_RENAMED;

		if (!git_oid_equal(&head2idx->old_file.id, &head2idx->new_file.id))
			st |= GIT_STATUS_INDEX_MODIFIED;
		break;
	case GIT_DELTA_TYPECHANGE:
		st = GIT_STATUS_INDEX_TYPECHANGE;
		break;
	case GIT_DELTA_CONFLICTED:
		st = GIT_STATUS_CONFLICTED;
		break;
	default:
		break;
	}

	return st;
}

static unsigned int workdir_delta2status(
	git_diff *diff, git_diff_delta *idx2wd)
{
	git_status_t st = GIT_STATUS_CURRENT;

	switch (idx2wd->status) {
	case GIT_DELTA_ADDED:
	case GIT_DELTA_COPIED:
	case GIT_DELTA_UNTRACKED:
		st = GIT_STATUS_WT_NEW;
		break;
	case GIT_DELTA_UNREADABLE:
		st = GIT_STATUS_WT_UNREADABLE;
		break;
	case GIT_DELTA_DELETED:
		st = GIT_STATUS_WT_DELETED;
		break;
	case GIT_DELTA_MODIFIED:
		st = GIT_STATUS_WT_MODIFIED;
		break;
	case GIT_DELTA_IGNORED:
		st = GIT_STATUS_IGNORED;
		break;
	case GIT_DELTA_RENAMED:
		st = GIT_STATUS_WT_RENAMED;

		if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id)) {
			/* if OIDs don't match, we might need to calculate them now to
			 * discern between RENAMED vs RENAMED+MODIFED
			 */
			if (git_oid_iszero(&idx2wd->old_file.id) &&
				diff->old_src == GIT_ITERATOR_TYPE_WORKDIR &&
				!git_diff__oid_for_file(
					&idx2wd->old_file.id, diff, idx2wd->old_file.path,
					idx2wd->old_file.mode, idx2wd->old_file.size))
			idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_ID;

			if (git_oid_iszero(&idx2wd->new_file.id) &&
				diff->new_src == GIT_ITERATOR_TYPE_WORKDIR &&
				!git_diff__oid_for_file(
					&idx2wd->new_file.id, diff, idx2wd->new_file.path,
					idx2wd->new_file.mode, idx2wd->new_file.size))
				idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_ID;

			if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id))
				st |= GIT_STATUS_WT_MODIFIED;
		}
		break;
	case GIT_DELTA_TYPECHANGE:
		st = GIT_STATUS_WT_TYPECHANGE;
		break;
	case GIT_DELTA_CONFLICTED:
		st = GIT_STATUS_CONFLICTED;
		break;
	default:
		break;
	}

	return st;
}

static bool status_is_included(
	git_status_list *status,
	git_diff_delta *head2idx,
	git_diff_delta *idx2wd)
{
	if (!(status->opts.flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES))
		return 1;

	/* if excluding submodules and this is a submodule everywhere */
	if (head2idx) {
		if (head2idx->status != GIT_DELTA_ADDED &&
			head2idx->old_file.mode != GIT_FILEMODE_COMMIT)
			return 1;
		if (head2idx->status != GIT_DELTA_DELETED &&
			head2idx->new_file.mode != GIT_FILEMODE_COMMIT)
			return 1;
	}
	if (idx2wd) {
		if (idx2wd->status != GIT_DELTA_ADDED &&
			idx2wd->old_file.mode != GIT_FILEMODE_COMMIT)
			return 1;
		if (idx2wd->status != GIT_DELTA_DELETED &&
			idx2wd->new_file.mode != GIT_FILEMODE_COMMIT)
			return 1;
	}

	/* only get here if every valid mode is GIT_FILEMODE_COMMIT */
	return 0;
}

static git_status_t status_compute(
	git_status_list *status,
	git_diff_delta *head2idx,
	git_diff_delta *idx2wd)
{
	git_status_t st = GIT_STATUS_CURRENT;

	if (head2idx)
		st |= index_delta2status(head2idx);

	if (idx2wd)
		st |= workdir_delta2status(status->idx2wd, idx2wd);

	return st;
}

static int status_collect(
	git_diff_delta *head2idx,
	git_diff_delta *idx2wd,
	void *payload)
{
	git_status_list *status = payload;
	git_status_entry *status_entry;

	if (!status_is_included(status, head2idx, idx2wd))
		return 0;

	status_entry = git__malloc(sizeof(git_status_entry));
	GITERR_CHECK_ALLOC(status_entry);

	status_entry->status = status_compute(status, head2idx, idx2wd);
	status_entry->head_to_index = head2idx;
	status_entry->index_to_workdir = idx2wd;

	return git_vector_insert(&status->paired, status_entry);
}

GIT_INLINE(int) status_entry_cmp_base(
	const void *a,
	const void *b,
	int (*strcomp)(const char *a, const char *b))
{
	const git_status_entry *entry_a = a;
	const git_status_entry *entry_b = b;
	const git_diff_delta *delta_a, *delta_b;

	delta_a = entry_a->index_to_workdir ? entry_a->index_to_workdir :
		entry_a->head_to_index;
	delta_b = entry_b->index_to_workdir ? entry_b->index_to_workdir :
		entry_b->head_to_index;

	if (!delta_a && delta_b)
		return -1;
	if (delta_a && !delta_b)
		return 1;
	if (!delta_a && !delta_b)
		return 0;

	return strcomp(delta_a->new_file.path, delta_b->new_file.path);
}

static int status_entry_icmp(const void *a, const void *b)
{
	return status_entry_cmp_base(a, b, git__strcasecmp);
}

static int status_entry_cmp(const void *a, const void *b)
{
	return status_entry_cmp_base(a, b, git__strcmp);
}

static git_status_list *git_status_list_alloc(git_index *index)
{
	git_status_list *status = NULL;
	int (*entrycmp)(const void *a, const void *b);

	if (!(status = git__calloc(1, sizeof(git_status_list))))
		return NULL;

	entrycmp = index->ignore_case ? status_entry_icmp : status_entry_cmp;

	if (git_vector_init(&status->paired, 0, entrycmp) < 0) {
		git__free(status);
		return NULL;
	}

	return status;
}

static int status_validate_options(const git_status_options *opts)
{
	if (!opts)
		return 0;

	GITERR_CHECK_VERSION(opts, GIT_STATUS_OPTIONS_VERSION, "git_status_options");

	if (opts->show > GIT_STATUS_SHOW_WORKDIR_ONLY) {
		giterr_set(GITERR_INVALID, "unknown status 'show' option");
		return -1;
	}

	if ((opts->flags & GIT_STATUS_OPT_NO_REFRESH) != 0 &&
		(opts->flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0) {
		giterr_set(GITERR_INVALID, "updating index from status "
			"is not allowed when index refresh is disabled");
		return -1;
	}

	return 0;
}

int git_status_list_new(
	git_status_list **out,
	git_repository *repo,
	const git_status_options *opts)
{
	git_index *index = NULL;
	git_status_list *status = NULL;
	git_diff_options diffopt = GIT_DIFF_OPTIONS_INIT;
	git_diff_find_options findopt = GIT_DIFF_FIND_OPTIONS_INIT;
	git_tree *head = NULL;
	git_status_show_t show =
		opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
	int error = 0;
	unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS;

	*out = NULL;

	if (status_validate_options(opts) < 0)
		return -1;

	if ((error = git_repository__ensure_not_bare(repo, "status")) < 0 ||
		(error = git_repository_index(&index, repo)) < 0)
		return error;

	/* if there is no HEAD, that's okay - we'll make an empty iterator */
	if ((error = git_repository_head_tree(&head, repo)) < 0) {
		if (error != GIT_ENOTFOUND && error != GIT_EUNBORNBRANCH)
			goto done;
		giterr_clear();
	}

	/* refresh index from disk unless prevented */
	if ((flags & GIT_STATUS_OPT_NO_REFRESH) == 0 &&
		git_index_read(index, false) < 0)
		giterr_clear();

	status = git_status_list_alloc(index);
	GITERR_CHECK_ALLOC(status);

	if (opts) {
		memcpy(&status->opts, opts, sizeof(git_status_options));
		memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec));
	}

	diffopt.flags = GIT_DIFF_INCLUDE_TYPECHANGE;
	findopt.flags = GIT_DIFF_FIND_FOR_UNTRACKED;

	if ((flags & GIT_STATUS_OPT_INCLUDE_UNTRACKED) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNTRACKED;
	if ((flags & GIT_STATUS_OPT_INCLUDE_IGNORED) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_IGNORED;
	if ((flags & GIT_STATUS_OPT_INCLUDE_UNMODIFIED) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNMODIFIED;
	if ((flags & GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_UNTRACKED_DIRS;
	if ((flags & GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_DISABLE_PATHSPEC_MATCH;
	if ((flags & GIT_STATUS_OPT_RECURSE_IGNORED_DIRS) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_IGNORED_DIRS;
	if ((flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES;
	if ((flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_UPDATE_INDEX;
	if ((flags & GIT_STATUS_OPT_INCLUDE_UNREADABLE) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNREADABLE;
	if ((flags & GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED) != 0)
		diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED;

	if ((flags & GIT_STATUS_OPT_RENAMES_FROM_REWRITES) != 0)
		findopt.flags = findopt.flags |
			GIT_DIFF_FIND_AND_BREAK_REWRITES |
			GIT_DIFF_FIND_RENAMES_FROM_REWRITES |
			GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY;

	if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) {
		if ((error = git_diff_tree_to_index(
				&status->head2idx, repo, head, index, &diffopt)) < 0)
			goto done;

		if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 &&
			(error = git_diff_find_similar(status->head2idx, &findopt)) < 0)
			goto done;
	}

	if (show != GIT_STATUS_SHOW_INDEX_ONLY) {
		if ((error = git_diff_index_to_workdir(
				&status->idx2wd, repo, index, &diffopt)) < 0) {
			goto done;
		}

		if ((flags & GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR) != 0 &&
			(error = git_diff_find_similar(status->idx2wd, &findopt)) < 0)
			goto done;
	}

	error = git_diff__paired_foreach(
		status->head2idx, status->idx2wd, status_collect, status);
	if (error < 0)
		goto done;

	if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY)
		git_vector_set_cmp(&status->paired, status_entry_cmp);
	if (flags & GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY)
		git_vector_set_cmp(&status->paired, status_entry_icmp);

	if ((flags &
		 (GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
		  GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR |
		  GIT_STATUS_OPT_SORT_CASE_SENSITIVELY |
		  GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY)) != 0)
		git_vector_sort(&status->paired);

done:
	if (error < 0) {
		git_status_list_free(status);
		status = NULL;
	}

	*out = status;

	git_tree_free(head);
	git_index_free(index);

	return error;
}

size_t git_status_list_entrycount(git_status_list *status)
{
	assert(status);

	return status->paired.length;
}

const git_status_entry *git_status_byindex(git_status_list *status, size_t i)
{
	assert(status);

	return git_vector_get(&status->paired, i);
}

void git_status_list_free(git_status_list *status)
{
	if (status == NULL)
		return;

	git_diff_free(status->head2idx);
	git_diff_free(status->idx2wd);

	git_vector_free_deep(&status->paired);

	git__memzero(status, sizeof(*status));
	git__free(status);
}

int git_status_foreach_ext(
	git_repository *repo,
	const git_status_options *opts,
	git_status_cb cb,
	void *payload)
{
	git_status_list *status;
	const git_status_entry *status_entry;
	size_t i;
	int error = 0;

	if ((error = git_status_list_new(&status, repo, opts)) < 0) {
		return error;
	}

	git_vector_foreach(&status->paired, i, status_entry) {
		const char *path = status_entry->head_to_index ?
			status_entry->head_to_index->old_file.path :
			status_entry->index_to_workdir->old_file.path;

		if ((error = cb(path, status_entry->status, payload)) != 0) {
			giterr_set_after_callback(error);
			break;
		}
	}

	git_status_list_free(status);

	return error;
}

int git_status_foreach(git_repository *repo, git_status_cb cb, void *payload)
{
	return git_status_foreach_ext(repo, NULL, cb, payload);
}

struct status_file_info {
	char *expected;
	unsigned int count;
	unsigned int status;
	int fnm_flags;
	int ambiguous;
};

static int get_one_status(const char *path, unsigned int status, void *data)
{
	struct status_file_info *sfi = data;
	int (*strcomp)(const char *a, const char *b);

	sfi->count++;
	sfi->status = status;

	strcomp = (sfi->fnm_flags & FNM_CASEFOLD) ? git__strcasecmp : git__strcmp;

	if (sfi->count > 1 ||
		(strcomp(sfi->expected, path) != 0 &&
		 p_fnmatch(sfi->expected, path, sfi->fnm_flags) != 0))
	{
		sfi->ambiguous = true;
		return GIT_EAMBIGUOUS; /* giterr_set will be done by caller */
	}

	return 0;
}

int git_status_file(
	unsigned int *status_flags,
	git_repository *repo,
	const char *path)
{
	int error;
	git_status_options opts = GIT_STATUS_OPTIONS_INIT;
	struct status_file_info sfi = {0};
	git_index *index;

	assert(status_flags && repo && path);

	if ((error = git_repository_index__weakptr(&index, repo)) < 0)
		return error;

	if ((sfi.expected = git__strdup(path)) == NULL)
		return -1;
	if (index->ignore_case)
		sfi.fnm_flags = FNM_CASEFOLD;

	opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
	opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED |
		GIT_STATUS_OPT_RECURSE_IGNORED_DIRS |
		GIT_STATUS_OPT_INCLUDE_UNTRACKED |
		GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS |
		GIT_STATUS_OPT_INCLUDE_UNMODIFIED |
		GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH;
	opts.pathspec.count = 1;
	opts.pathspec.strings = &sfi.expected;

	error = git_status_foreach_ext(repo, &opts, get_one_status, &sfi);

	if (error < 0 && sfi.ambiguous) {
		giterr_set(GITERR_INVALID,
			"ambiguous path '%s' given to git_status_file", sfi.expected);
		error = GIT_EAMBIGUOUS;
	}

	if (!error && !sfi.count) {
		giterr_set(GITERR_INVALID,
			"attempt to get status of nonexistent file '%s'", path);
		error = GIT_ENOTFOUND;
	}

	*status_flags = sfi.status;

	git__free(sfi.expected);

	return error;
}

int git_status_should_ignore(
	int *ignored,
	git_repository *repo,
	const char *path)
{
	return git_ignore_path_is_ignored(ignored, repo, path);
}

int git_status_init_options(git_status_options *opts, unsigned int version)
{
	GIT_INIT_STRUCTURE_FROM_TEMPLATE(
		opts, version, git_status_options, GIT_STATUS_OPTIONS_INIT);
	return 0;
}

int git_status_list_get_perfdata(
	git_diff_perfdata *out, const git_status_list *status)
{
	assert(out);
	GITERR_CHECK_VERSION(out, GIT_DIFF_PERFDATA_VERSION, "git_diff_perfdata");

	out->stat_calls = 0;
	out->oid_calculations = 0;

	if (status->head2idx) {
		out->stat_calls += status->head2idx->perf.stat_calls;
		out->oid_calculations += status->head2idx->perf.oid_calculations;
	}
	if (status->idx2wd) {
		out->stat_calls += status->idx2wd->perf.stat_calls;
		out->oid_calculations += status->idx2wd->perf.oid_calculations;
	}

	return 0;
}

