/*
 * Copyright (C) 2009-2012 the libgit2 contributors
 *
 * 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 "fileops.h"
#include "hash.h"
#include "filter.h"
#include "repository.h"

#include "git2/attr.h"

struct crlf_attrs {
	int crlf_action;
	int eol;
};

struct crlf_filter {
	git_filter f;
	struct crlf_attrs attrs;
};

static int check_crlf(const char *value)
{
	if (GIT_ATTR_TRUE(value))
		return GIT_CRLF_TEXT;

	if (GIT_ATTR_FALSE(value))
		return GIT_CRLF_BINARY;

	if (GIT_ATTR_UNSPECIFIED(value))
		return GIT_CRLF_GUESS;

	if (strcmp(value, "input") == 0)
		return GIT_CRLF_INPUT;

	if (strcmp(value, "auto") == 0)
		return GIT_CRLF_AUTO;

	return GIT_CRLF_GUESS;
}

static int check_eol(const char *value)
{
	if (GIT_ATTR_UNSPECIFIED(value))
		return GIT_EOL_UNSET;

	if (strcmp(value, "lf") == 0)
		return GIT_EOL_LF;

	if (strcmp(value, "crlf") == 0)
		return GIT_EOL_CRLF;

	return GIT_EOL_UNSET;
}

static int crlf_input_action(struct crlf_attrs *ca)
{
	if (ca->crlf_action == GIT_CRLF_BINARY)
		return GIT_CRLF_BINARY;

	if (ca->eol == GIT_EOL_LF)
		return GIT_CRLF_INPUT;

	if (ca->eol == GIT_EOL_CRLF)
		return GIT_CRLF_CRLF;

	return ca->crlf_action;
}

static int crlf_load_attributes(struct crlf_attrs *ca, git_repository *repo, const char *path)
{
#define NUM_CONV_ATTRS 3

	static const char *attr_names[NUM_CONV_ATTRS] = {
		"crlf", "eol", "text",
	};

	const char *attr_vals[NUM_CONV_ATTRS];
	int error;

	error = git_attr_get_many(attr_vals,
		repo, 0, path, NUM_CONV_ATTRS, attr_names);

	if (error == GIT_ENOTFOUND) {
		ca->crlf_action = GIT_CRLF_GUESS;
		ca->eol = GIT_EOL_UNSET;
		return 0;
	}

	if (error == 0) {
		ca->crlf_action = check_crlf(attr_vals[2]); /* text */
		if (ca->crlf_action == GIT_CRLF_GUESS)
			ca->crlf_action = check_crlf(attr_vals[0]); /* clrf */

		ca->eol = check_eol(attr_vals[1]); /* eol */
		return 0;
	}

	return -1;
}

static int drop_crlf(git_buf *dest, const git_buf *source)
{
	const char *scan = source->ptr, *next;
	const char *scan_end = git_buf_cstr(source) + git_buf_len(source);

	/* Main scan loop.  Find the next carriage return and copy the
	 * whole chunk up to that point to the destination buffer.
	 */
	while ((next = memchr(scan, '\r', scan_end - scan)) != NULL) {
		/* copy input up to \r */
		if (next > scan)
			git_buf_put(dest, scan, next - scan);

		/* Do not drop \r unless it is followed by \n */
		if (*(next + 1) != '\n')
			git_buf_putc(dest, '\r');

		scan = next + 1;
	}

	/* If there was no \r, then tell the library to skip this filter */
	if (scan == source->ptr)
		return -1;

	/* Copy remaining input into dest */
	git_buf_put(dest, scan, scan_end - scan);
	return 0;
}

static int crlf_apply_to_odb(git_filter *self, git_buf *dest, const git_buf *source)
{
	struct crlf_filter *filter = (struct crlf_filter *)self;

	assert(self && dest && source);

	/* Empty file? Nothing to do */
	if (git_buf_len(source) == 0)
		return 0;

	/* Heuristics to see if we can skip the conversion.
	 * Straight from Core Git.
	 */
	if (filter->attrs.crlf_action == GIT_CRLF_AUTO ||
		filter->attrs.crlf_action == GIT_CRLF_GUESS) {

		git_buf_text_stats stats;

		/* Check heuristics for binary vs text... */
		if (git_buf_text_gather_stats(&stats, source, false))
			return -1;

		/*
		 * We're currently not going to even try to convert stuff
		 * that has bare CR characters. Does anybody do that crazy
		 * stuff?
		 */
		if (stats.cr != stats.crlf)
			return -1;

#if 0
		if (crlf_action == CRLF_GUESS) {
			/*
			 * If the file in the index has any CR in it, do not convert.
			 * This is the new safer autocrlf handling.
			 */
			if (has_cr_in_index(path))
				return 0;
		}
#endif

		if (!stats.cr)
			return -1;
	}

	/* Actually drop the carriage returns */
	return drop_crlf(dest, source);
}

static int convert_line_endings(git_buf *dest, const git_buf *source, const char *ending)
{
	const char *scan = git_buf_cstr(source),
				  *next,
				  *scan_end = git_buf_cstr(source) + git_buf_len(source);

	while ((next = memchr(scan, '\n', scan_end - scan)) != NULL) {
		if (next > scan)
			git_buf_put(dest, scan, next-scan);
		git_buf_puts(dest, ending);
		scan = next + 1;
	}

	git_buf_put(dest, scan, scan_end - scan);
	return 0;
}

static const char *line_ending(struct crlf_filter *filter)
{
	switch (filter->attrs.crlf_action) {
	case GIT_CRLF_BINARY:
	case GIT_CRLF_INPUT:
		return "\n";

	case GIT_CRLF_CRLF:
		return "\r\n";

	case GIT_CRLF_AUTO:
	case GIT_CRLF_TEXT:
	case GIT_CRLF_GUESS:
		break;

	default:
		goto line_ending_error;
	}

	switch (filter->attrs.eol) {
	case GIT_EOL_UNSET:
		return GIT_EOL_NATIVE == GIT_EOL_CRLF
			? "\r\n"
			: "\n";

	case GIT_EOL_CRLF:
		return "\r\n";

	case GIT_EOL_LF:
		return "\n";

	default:
		goto line_ending_error;
	}

line_ending_error:
	giterr_set(GITERR_INVALID, "Invalid input to line ending filter");
	return NULL;
}

static int crlf_apply_to_workdir(git_filter *self, git_buf *dest, const git_buf *source)
{
	struct crlf_filter *filter = (struct crlf_filter *)self;
	const char *workdir_ending = NULL;

	assert (self && dest && source);

	/* Empty file? Nothing to do. */
	if (git_buf_len(source) == 0)
		return 0;

	/* Determine proper line ending */
	workdir_ending = line_ending(filter);
	if (!workdir_ending) return -1;

	/* If the line ending is '\n', just copy the input */
	if (!strcmp(workdir_ending, "\n"))
		return git_buf_puts(dest, git_buf_cstr(source));

	return convert_line_endings(dest, source, workdir_ending);
}

static int find_and_add_filter(
	git_vector *filters, git_repository *repo, const char *path,
	int (*apply)(struct git_filter *self, git_buf *dest, const git_buf *source))
{
	struct crlf_attrs ca;
	struct crlf_filter *filter;
	int error;

	/* Load gitattributes for the path */
	if ((error = crlf_load_attributes(&ca, repo, path)) < 0)
		return error;

	/*
	 * Use the core Git logic to see if we should perform CRLF for this file
	 * based on its attributes & the value of `core.autocrlf`
	 */
	ca.crlf_action = crlf_input_action(&ca);

	if (ca.crlf_action == GIT_CRLF_BINARY)
		return 0;

	if (ca.crlf_action == GIT_CRLF_GUESS) {
		int auto_crlf;

		if ((error = git_repository__cvar(&auto_crlf, repo, GIT_CVAR_AUTO_CRLF)) < 0)
			return error;

		if (auto_crlf == GIT_AUTO_CRLF_FALSE)
			return 0;
	}

	/* If we're good, we create a new filter object and push it
	 * into the filters array */
	filter = git__malloc(sizeof(struct crlf_filter));
	GITERR_CHECK_ALLOC(filter);

	filter->f.apply = apply;
	filter->f.do_free = NULL;
	memcpy(&filter->attrs, &ca, sizeof(struct crlf_attrs));

	return git_vector_insert(filters, filter);
}

int git_filter_add__crlf_to_odb(git_vector *filters, git_repository *repo, const char *path)
{
	return find_and_add_filter(filters, repo, path, &crlf_apply_to_odb);
}

int git_filter_add__crlf_to_workdir(git_vector *filters, git_repository *repo, const char *path)
{
	return find_and_add_filter(filters, repo, path, &crlf_apply_to_workdir);
}
