/*
 * 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 "git2/common.h"
#include "git2/object.h"
#include "git2/repository.h"
#include "git2/odb_backend.h"

#include "common.h"
#include "filebuf.h"
#include "blob.h"
#include "filter.h"
#include "buf_text.h"

const void *git_blob_rawcontent(const git_blob *blob)
{
	assert(blob);
	return git_odb_object_data(blob->odb_object);
}

git_off_t git_blob_rawsize(const git_blob *blob)
{
	assert(blob);
	return (git_off_t)git_odb_object_size(blob->odb_object);
}

int git_blob__getbuf(git_buf *buffer, git_blob *blob)
{
	return git_buf_set(
		buffer,
		git_odb_object_data(blob->odb_object),
		git_odb_object_size(blob->odb_object));
}

void git_blob__free(void *blob)
{
	git_odb_object_free(((git_blob *)blob)->odb_object);
	git__free(blob);
}

int git_blob__parse(void *blob, git_odb_object *odb_obj)
{
	assert(blob);
	git_cached_obj_incref((git_cached_obj *)odb_obj);
	((git_blob *)blob)->odb_object = odb_obj;
	return 0;
}

int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len)
{
	int error;
	git_odb *odb;
	git_odb_stream *stream;

	if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
		(error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < 0)
		return error;

	if ((error = stream->write(stream, buffer, len)) == 0)
		error = stream->finalize_write(oid, stream);

	stream->free(stream);
	return error;
}

static int write_file_stream(
	git_oid *oid, git_odb *odb, const char *path, git_off_t file_size)
{
	int fd, error;
	char buffer[4096];
	git_odb_stream *stream = NULL;
	ssize_t read_len = -1, written = 0;

	if ((error = git_odb_open_wstream(
			&stream, odb, (size_t)file_size, GIT_OBJ_BLOB)) < 0)
		return error;

	if ((fd = git_futils_open_ro(path)) < 0) {
		stream->free(stream);
		return -1;
	}

	while (!error && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) {
		error = stream->write(stream, buffer, read_len);
		written += read_len;
	}

	p_close(fd);

	if (written != file_size || read_len < 0) {
		giterr_set(GITERR_OS, "Failed to read file into stream");
		error = -1;
	}

	if (!error)
		error = stream->finalize_write(oid, stream);

	stream->free(stream);
	return error;
}

static int write_file_filtered(
	git_oid *oid,
	git_odb *odb,
	const char *full_path,
	git_vector *filters)
{
	int error;
	git_buf source = GIT_BUF_INIT;
	git_buf dest = GIT_BUF_INIT;

	if ((error = git_futils_readbuffer(&source, full_path)) < 0)
		return error;

	error = git_filters_apply(&dest, &source, filters);

	/* Free the source as soon as possible. This can be big in memory,
	 * and we don't want to ODB write to choke */
	git_buf_free(&source);

	/* Write the file to disk if it was properly filtered */
	if (!error)
		error = git_odb_write(oid, odb, dest.ptr, dest.size, GIT_OBJ_BLOB);

	git_buf_free(&dest);
	return error;
}

static int write_symlink(
	git_oid *oid, git_odb *odb, const char *path, size_t link_size)
{
	char *link_data;
	ssize_t read_len;
	int error;

	link_data = git__malloc(link_size);
	GITERR_CHECK_ALLOC(link_data);

	read_len = p_readlink(path, link_data, link_size);
	if (read_len != (ssize_t)link_size) {
		giterr_set(GITERR_OS, "Failed to create blob.  Can't read symlink '%s'", path);
		git__free(link_data);
		return -1;
	}

	error = git_odb_write(oid, odb, (void *)link_data, link_size, GIT_OBJ_BLOB);
	git__free(link_data);
	return error;
}

static int blob_create_internal(git_oid *oid, git_repository *repo, const char *content_path, const char *hint_path, bool try_load_filters)
{
	int error;
	struct stat st;
	git_odb *odb = NULL;
	git_off_t size;

	assert(hint_path || !try_load_filters);

	if ((error = git_path_lstat(content_path, &st)) < 0 || (error = git_repository_odb__weakptr(&odb, repo)) < 0)
		return error;

	size = st.st_size;

	if (S_ISLNK(st.st_mode)) {
		error = write_symlink(oid, odb, content_path, (size_t)size);
	} else {
		git_vector write_filters = GIT_VECTOR_INIT;
		int filter_count = 0;

		if (try_load_filters) {
			/* Load the filters for writing this file to the ODB */
			filter_count = git_filters_load(
				&write_filters, repo, hint_path, GIT_FILTER_TO_ODB);
		}

		if (filter_count < 0) {
			/* Negative value means there was a critical error */
			error = filter_count;
		} else if (filter_count == 0) {
			/* No filters need to be applied to the document: we can stream
			 * directly from disk */
			error = write_file_stream(oid, odb, content_path, size);
		} else {
			/* We need to apply one or more filters */
			error = write_file_filtered(oid, odb, content_path, &write_filters);
		}

		git_filters_free(&write_filters);

		/*
		 * TODO: eventually support streaming filtered files, for files
		 * which are bigger than a given threshold. This is not a priority
		 * because applying a filter in streaming mode changes the final
		 * size of the blob, and without knowing its final size, the blob
		 * cannot be written in stream mode to the ODB.
		 *
		 * The plan is to do streaming writes to a tempfile on disk and then
		 * opening streaming that file to the ODB, using
		 * `write_file_stream`.
		 *
		 * CAREFULLY DESIGNED APIS YO
		 */
	}

	return error;
}

int git_blob_create_fromworkdir(git_oid *oid, git_repository *repo, const char *path)
{
	git_buf full_path = GIT_BUF_INIT;
	const char *workdir;
	int error;

	if ((error = git_repository__ensure_not_bare(repo, "create blob from file")) < 0)
		return error;

	workdir = git_repository_workdir(repo);

	if (git_buf_joinpath(&full_path, workdir, path) < 0) {
		git_buf_free(&full_path);
		return -1;
	}

	error = blob_create_internal(
		oid, repo, git_buf_cstr(&full_path),
		git_buf_cstr(&full_path) + strlen(workdir), true);

	git_buf_free(&full_path);
	return error;
}

int git_blob_create_fromdisk(git_oid *oid, git_repository *repo, const char *path)
{
	int error;
	git_buf full_path = GIT_BUF_INIT;
	const char *workdir, *hintpath;

	if ((error = git_path_prettify(&full_path, path, NULL)) < 0) {
		git_buf_free(&full_path);
		return error;
	}

	hintpath = git_buf_cstr(&full_path);
	workdir  = git_repository_workdir(repo);

	if (workdir && !git__prefixcmp(hintpath, workdir))
		hintpath += strlen(workdir);

	error = blob_create_internal(
		oid, repo, git_buf_cstr(&full_path), hintpath, true);

	git_buf_free(&full_path);
	return error;
}

#define BUFFER_SIZE 4096

int git_blob_create_fromchunks(
	git_oid *oid,
	git_repository *repo,
	const char *hintpath,
	int (*source_cb)(char *content, size_t max_length, void *payload),
	void *payload)
{
	int error = -1, read_bytes;
	char *content = NULL;
	git_filebuf file = GIT_FILEBUF_INIT;
	git_buf path = GIT_BUF_INIT;

	if (git_buf_join_n(
		&path, '/', 3, 
		git_repository_path(repo),
		GIT_OBJECTS_DIR, 
		"streamed") < 0)
			goto cleanup;

	content = git__malloc(BUFFER_SIZE);
	GITERR_CHECK_ALLOC(content);

	if (git_filebuf_open(&file, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY) < 0)
		goto cleanup;

	while (1) {
		read_bytes = source_cb(content, BUFFER_SIZE, payload);

		assert(read_bytes <= BUFFER_SIZE);

		if (read_bytes <= 0)
			break;

		if (git_filebuf_write(&file, content, read_bytes) < 0)
			goto cleanup;
	}

	if (read_bytes < 0)
		goto cleanup;

	if (git_filebuf_flush(&file) < 0)
		goto cleanup;

	error = blob_create_internal(oid, repo, file.path_lock, hintpath, hintpath != NULL);

cleanup:
	git_buf_free(&path);
	git_filebuf_cleanup(&file);
	git__free(content);
	return error;
}

int git_blob_is_binary(git_blob *blob)
{
	git_buf content;

	assert(blob);

	content.ptr = blob->odb_object->buffer;
	content.size = min(blob->odb_object->cached.size, 4000);

	return git_buf_text_is_binary(&content);
}
