/*
 * 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 "vector.h"
#include "diff.h"
#include "patch_generate.h"

#define DIFF_RENAME_FILE_SEPARATOR " => "
#define STATS_FULL_MIN_SCALE 7

typedef struct {
	size_t insertions;
	size_t deletions;
} diff_file_stats;

struct git_diff_stats {
	git_diff *diff;
	diff_file_stats *filestats;

	size_t files_changed;
	size_t insertions;
	size_t deletions;
	size_t renames;

	size_t max_name;
	size_t max_filestat;
	int max_digits;
};

static int digits_for_value(size_t val)
{
	int count = 1;
	size_t placevalue = 10;

	while (val >= placevalue) {
		++count;
		placevalue *= 10;
	}

	return count;
}

int git_diff_file_stats__full_to_buf(
	git_buf *out,
	const git_diff_delta *delta,
	const diff_file_stats *filestat,
	const git_diff_stats *stats,
	size_t width)
{
	const char *old_path = NULL, *new_path = NULL;
	size_t padding, old_size, new_size;

	old_path = delta->old_file.path;
	new_path = delta->new_file.path;
	old_size = delta->old_file.size;
	new_size = delta->new_file.size;

	if (git_buf_printf(out, " %s", old_path) < 0)
		goto on_error;

	if (strcmp(old_path, new_path) != 0) {
		padding = stats->max_name - strlen(old_path) - strlen(new_path);

		if (git_buf_printf(out, DIFF_RENAME_FILE_SEPARATOR "%s", new_path) < 0)
			goto on_error;
	} else {
		padding = stats->max_name - strlen(old_path);

		if (stats->renames > 0)
			padding += strlen(DIFF_RENAME_FILE_SEPARATOR);
	}

	if (git_buf_putcn(out, ' ', padding) < 0 ||
		git_buf_puts(out, " | ") < 0)
		goto on_error;

	if (delta->flags & GIT_DIFF_FLAG_BINARY) {
		if (git_buf_printf(out,
				"Bin %" PRIuZ " -> %" PRIuZ " bytes", old_size, new_size) < 0)
			goto on_error;
	}
	else {
		if (git_buf_printf(out,
				"%*" PRIuZ, stats->max_digits,
				filestat->insertions + filestat->deletions) < 0)
			goto on_error;

		if (filestat->insertions || filestat->deletions) {
			if (git_buf_putc(out, ' ') < 0)
				goto on_error;

			if (!width) {
				if (git_buf_putcn(out, '+', filestat->insertions) < 0 ||
					git_buf_putcn(out, '-', filestat->deletions) < 0)
					goto on_error;
			} else {
				size_t total = filestat->insertions + filestat->deletions;
				size_t full = (total * width + stats->max_filestat / 2) /
					stats->max_filestat;
				size_t plus = full * filestat->insertions / total;
				size_t minus = full - plus;

				if (git_buf_putcn(out, '+', max(plus,  1)) < 0 ||
					git_buf_putcn(out, '-', max(minus, 1)) < 0)
					goto on_error;
			}
		}
	}

	git_buf_putc(out, '\n');

on_error:
	return (git_buf_oom(out) ? -1 : 0);
}

int git_diff_file_stats__number_to_buf(
	git_buf *out,
	const git_diff_delta *delta,
	const diff_file_stats *filestats)
{
	int error;
	const char *path = delta->new_file.path;

	if (delta->flags & GIT_DIFF_FLAG_BINARY)
		error = git_buf_printf(out, "%-8c" "%-8c" "%s\n", '-', '-', path);
	else
		error = git_buf_printf(out, "%-8" PRIuZ "%-8" PRIuZ "%s\n",
			filestats->insertions, filestats->deletions, path);

	return error;
}

int git_diff_file_stats__summary_to_buf(
	git_buf *out,
	const git_diff_delta *delta)
{
	if (delta->old_file.mode != delta->new_file.mode) {
		if (delta->old_file.mode == 0) {
			git_buf_printf(out, " create mode %06o %s\n",
				delta->new_file.mode, delta->new_file.path);
		}
		else if (delta->new_file.mode == 0) {
			git_buf_printf(out, " delete mode %06o %s\n",
				delta->old_file.mode, delta->old_file.path);
		}
		else {
			git_buf_printf(out, " mode change %06o => %06o %s\n",
				delta->old_file.mode, delta->new_file.mode, delta->new_file.path);
		}
	}

	return 0;
}

int git_diff_get_stats(
	git_diff_stats **out,
	git_diff *diff)
{
	size_t i, deltas;
	size_t total_insertions = 0, total_deletions = 0;
	git_diff_stats *stats = NULL;
	int error = 0;

	assert(out && diff);

	stats = git__calloc(1, sizeof(git_diff_stats));
	GITERR_CHECK_ALLOC(stats);

	deltas = git_diff_num_deltas(diff);

	stats->filestats = git__calloc(deltas, sizeof(diff_file_stats));
	if (!stats->filestats) {
		git__free(stats);
		return -1;
	}

	stats->diff = diff;
	GIT_REFCOUNT_INC(diff);

	for (i = 0; i < deltas && !error; ++i) {
		git_patch *patch = NULL;
		size_t add = 0, remove = 0, namelen;
		const git_diff_delta *delta;

		if ((error = git_patch_from_diff(&patch, diff, i)) < 0)
			break;

		/* keep a count of renames because it will affect formatting */
		delta = patch->delta;

		/* TODO ugh */
		namelen = strlen(delta->new_file.path);
		if (strcmp(delta->old_file.path, delta->new_file.path) != 0) {
			namelen += strlen(delta->old_file.path);
			stats->renames++;
		}

		/* and, of course, count the line stats */
		error = git_patch_line_stats(NULL, &add, &remove, patch);

		git_patch_free(patch);

		stats->filestats[i].insertions = add;
		stats->filestats[i].deletions = remove;

		total_insertions += add;
		total_deletions += remove;

		if (stats->max_name < namelen)
			stats->max_name = namelen;
		if (stats->max_filestat < add + remove)
			stats->max_filestat = add + remove;
	}

	stats->files_changed = deltas;
	stats->insertions = total_insertions;
	stats->deletions = total_deletions;
	stats->max_digits = digits_for_value(stats->max_filestat + 1);

	if (error < 0) {
		git_diff_stats_free(stats);
		stats = NULL;
	}

	*out = stats;
	return error;
}

size_t git_diff_stats_files_changed(
	const git_diff_stats *stats)
{
	assert(stats);

	return stats->files_changed;
}

size_t git_diff_stats_insertions(
	const git_diff_stats *stats)
{
	assert(stats);

	return stats->insertions;
}

size_t git_diff_stats_deletions(
	const git_diff_stats *stats)
{
	assert(stats);

	return stats->deletions;
}

int git_diff_stats_to_buf(
	git_buf *out,
	const git_diff_stats *stats,
	git_diff_stats_format_t format,
	size_t width)
{
	int error = 0;
	size_t i;
	const git_diff_delta *delta;

	assert(out && stats);

	if (format & GIT_DIFF_STATS_NUMBER) {
		for (i = 0; i < stats->files_changed; ++i) {
			if ((delta = git_diff_get_delta(stats->diff, i)) == NULL)
				continue;

			error = git_diff_file_stats__number_to_buf(
				out, delta, &stats->filestats[i]);
			if (error < 0)
				return error;
		}
	}

	if (format & GIT_DIFF_STATS_FULL) {
		if (width > 0) {
			if (width > stats->max_name + stats->max_digits + 5)
				width -= (stats->max_name + stats->max_digits + 5);
			if (width < STATS_FULL_MIN_SCALE)
				width = STATS_FULL_MIN_SCALE;
		}
		if (width > stats->max_filestat)
			width = 0;

		for (i = 0; i < stats->files_changed; ++i) {
			if ((delta = git_diff_get_delta(stats->diff, i)) == NULL)
				continue;

			error = git_diff_file_stats__full_to_buf(
				out, delta, &stats->filestats[i], stats, width);
			if (error < 0)
				return error;
		}
	}

	if (format & GIT_DIFF_STATS_FULL || format & GIT_DIFF_STATS_SHORT) {
		git_buf_printf(
			out, " %" PRIuZ " file%s changed",
			stats->files_changed, stats->files_changed != 1 ? "s" : "");

		if (stats->insertions || stats->deletions == 0)
			git_buf_printf(
				out, ", %" PRIuZ " insertion%s(+)",
				stats->insertions, stats->insertions != 1 ? "s" : "");

		if (stats->deletions || stats->insertions == 0)
			git_buf_printf(
				out, ", %" PRIuZ " deletion%s(-)",
				stats->deletions, stats->deletions != 1 ? "s" : "");

		git_buf_putc(out, '\n');

		if (git_buf_oom(out))
			return -1;
	}

	if (format & GIT_DIFF_STATS_INCLUDE_SUMMARY) {
		for (i = 0; i < stats->files_changed; ++i) {
			if ((delta = git_diff_get_delta(stats->diff, i)) == NULL)
				continue;

			error = git_diff_file_stats__summary_to_buf(out, delta);
			if (error < 0)
				return error;
		}
	}

	return error;
}

void git_diff_stats_free(git_diff_stats *stats)
{
	if (stats == NULL)
		return;

	git_diff_free(stats->diff); /* bumped refcount in constructor */
	git__free(stats->filestats);
	git__free(stats);
}
