/*
 * 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 "strmap.h"
#include "refdb.h"
#include "pool.h"
#include "reflog.h"
#include "signature.h"

#include "git2/signature.h"
#include "git2/sys/refs.h"
#include "git2/sys/refdb_backend.h"

GIT__USE_STRMAP

typedef struct {
	const char *name;
	void *payload;

	git_ref_t ref_type;
	union {
		git_oid id;
		char *symbolic;
	} target;
	git_reflog *reflog;

	const char *message;
	git_signature *sig;

	unsigned int committed :1,
		remove :1;
} transaction_node;

struct git_transaction {
	git_repository *repo;
	git_refdb *db;

	git_strmap *locks;
	git_pool pool;
};

int git_transaction_new(git_transaction **out, git_repository *repo)
{
	int error;
	git_pool pool;
	git_transaction *tx = NULL;

	assert(out && repo);

	if ((error = git_pool_init(&pool, 1, 0)) < 0)
		return error;

	tx = git_pool_mallocz(&pool, sizeof(git_transaction));
	if (!tx) {
		error = -1;
		goto on_error;
	}

	if ((error = git_strmap_alloc(&tx->locks)) < 0) {
		error = -1;
		goto on_error;
	}

	if ((error = git_repository_refdb(&tx->db, repo)) < 0)
		goto on_error;

	memcpy(&tx->pool, &pool, sizeof(git_pool));
	tx->repo = repo;
	*out = tx;
	return 0;

on_error:
	git_pool_clear(&pool);
	return error;
}

int git_transaction_lock_ref(git_transaction *tx, const char *refname)
{
	int error;
	transaction_node *node;

	assert(tx && refname);

	node = git_pool_mallocz(&tx->pool, sizeof(transaction_node));
	GITERR_CHECK_ALLOC(node);

	node->name = git_pool_strdup(&tx->pool, refname);
	GITERR_CHECK_ALLOC(node->name);

	if ((error = git_refdb_lock(&node->payload, tx->db, refname)) < 0)
		return error;

	git_strmap_insert(tx->locks, node->name, node, error);
	if (error < 0) 
		goto cleanup;

	return 0;

cleanup:
	git_refdb_unlock(tx->db, node->payload, false, false, NULL, NULL, NULL);

	return error;
}

static int find_locked(transaction_node **out, git_transaction *tx, const char *refname)
{
	git_strmap_iter pos;
	transaction_node *node;

	pos = git_strmap_lookup_index(tx->locks, refname);
	if (!git_strmap_valid_index(tx->locks, pos)) {
		giterr_set(GITERR_REFERENCE, "the specified reference is not locked");
		return GIT_ENOTFOUND;
	}

	node = git_strmap_value_at(tx->locks, pos);

	*out = node;
	return 0;
}

static int copy_common(transaction_node *node, git_transaction *tx, const git_signature *sig, const char *msg)
{
	if (sig && git_signature__pdup(&node->sig, sig, &tx->pool) < 0)
		return -1;

	if (!node->sig) {
		git_signature *tmp;
		int error;

		if (git_reference__log_signature(&tmp, tx->repo) < 0)
			return -1;

		/* make sure the sig we use is in our pool */
		error = git_signature__pdup(&node->sig, tmp, &tx->pool);
		git_signature_free(tmp);
		if (error < 0)
			return error;
	}

	if (msg) {
		node->message = git_pool_strdup(&tx->pool, msg);
		GITERR_CHECK_ALLOC(node->message);
	}

	return 0;
}

int git_transaction_set_target(git_transaction *tx, const char *refname, const git_oid *target, const git_signature *sig, const char *msg)
{
	int error;
	transaction_node *node;

	assert(tx && refname && target);

	if ((error = find_locked(&node, tx, refname)) < 0)
		return error;

	if ((error = copy_common(node, tx, sig, msg)) < 0)
		return error;

	git_oid_cpy(&node->target.id, target);
	node->ref_type = GIT_REF_OID;

	return 0;
}

int git_transaction_set_symbolic_target(git_transaction *tx, const char *refname, const char *target, const git_signature *sig, const char *msg)
{
	int error;
	transaction_node *node;

	assert(tx && refname && target);

	if ((error = find_locked(&node, tx, refname)) < 0)
		return error;

	if ((error = copy_common(node, tx, sig, msg)) < 0)
		return error;

	node->target.symbolic = git_pool_strdup(&tx->pool, target);
	GITERR_CHECK_ALLOC(node->target.symbolic);
	node->ref_type = GIT_REF_SYMBOLIC;

	return 0;
}

int git_transaction_remove(git_transaction *tx, const char *refname)
{
	int error;
	transaction_node *node;

	if ((error = find_locked(&node, tx, refname)) < 0)
		return error;

	node->remove = true;
	node->ref_type = GIT_REF_OID; /* the id will be ignored */

	return 0;
}

static int dup_reflog(git_reflog **out, const git_reflog *in, git_pool *pool)
{
	git_reflog *reflog;
	git_reflog_entry *entries;
	size_t len, i;

	reflog = git_pool_mallocz(pool, sizeof(git_reflog));
	GITERR_CHECK_ALLOC(reflog);

	reflog->ref_name = git_pool_strdup(pool, in->ref_name);
	GITERR_CHECK_ALLOC(reflog->ref_name);

	len = in->entries.length;
	reflog->entries.length = len;
	reflog->entries.contents = git_pool_mallocz(pool, len * sizeof(void *));
	GITERR_CHECK_ALLOC(reflog->entries.contents);

	entries = git_pool_mallocz(pool, len * sizeof(git_reflog_entry));
	GITERR_CHECK_ALLOC(entries);

	for (i = 0; i < len; i++) {
		const git_reflog_entry *src;
		git_reflog_entry *tgt;

		tgt = &entries[i];
		reflog->entries.contents[i] = tgt;

		src = git_vector_get(&in->entries, i);
		git_oid_cpy(&tgt->oid_old, &src->oid_old);
		git_oid_cpy(&tgt->oid_cur, &src->oid_cur);

		tgt->msg = git_pool_strdup(pool, src->msg);
		GITERR_CHECK_ALLOC(tgt->msg);

		if (git_signature__pdup(&tgt->committer, src->committer, pool) < 0)
			return -1;
	}


	*out = reflog;
	return 0;
}

int git_transaction_set_reflog(git_transaction *tx, const char *refname, const git_reflog *reflog)
{
	int error;
	transaction_node *node;

	assert(tx && refname && reflog);

	if ((error = find_locked(&node, tx, refname)) < 0)
		return error;

	if ((error = dup_reflog(&node->reflog, reflog, &tx->pool)) < 0)
		return error;

	return 0;
}

static int update_target(git_refdb *db, transaction_node *node)
{
	git_reference *ref;
	int error, update_reflog;

	if (node->ref_type == GIT_REF_OID) {
		ref = git_reference__alloc(node->name, &node->target.id, NULL);
	} else if (node->ref_type == GIT_REF_SYMBOLIC) {
		ref = git_reference__alloc_symbolic(node->name, node->target.symbolic);
	} else {
		abort();
	}

	GITERR_CHECK_ALLOC(ref);
	update_reflog = node->reflog == NULL;

	if (node->remove) {
		error =  git_refdb_unlock(db, node->payload, 2, false, ref, NULL, NULL);
	} else if (node->ref_type == GIT_REF_OID) {
		error = git_refdb_unlock(db, node->payload, true, update_reflog, ref, node->sig, node->message);
	} else if (node->ref_type == GIT_REF_SYMBOLIC) {
		error = git_refdb_unlock(db, node->payload, true, update_reflog, ref, node->sig, node->message);
	} else {
		abort();
	}

	git_reference_free(ref);
	node->committed = true;

	return error;
}

int git_transaction_commit(git_transaction *tx)
{
	transaction_node *node;
	git_strmap_iter pos;
	int error = 0;

	assert(tx);

	for (pos = kh_begin(tx->locks); pos < kh_end(tx->locks); pos++) {
		if (!git_strmap_has_data(tx->locks, pos))
			continue;

		node = git_strmap_value_at(tx->locks, pos);
		if (node->reflog) {
			if ((error = tx->db->backend->reflog_write(tx->db->backend, node->reflog)) < 0)
				return error;
		}

		if (node->ref_type != GIT_REF_INVALID) {
			if ((error = update_target(tx->db, node)) < 0)
				return error;
		}
	}

	return 0;
}

void git_transaction_free(git_transaction *tx)
{
	transaction_node *node;
	git_pool pool;
	git_strmap_iter pos;

	assert(tx);

	/* start by unlocking the ones we've left hanging, if any */
	for (pos = kh_begin(tx->locks); pos < kh_end(tx->locks); pos++) {
		if (!git_strmap_has_data(tx->locks, pos))
			continue;

		node = git_strmap_value_at(tx->locks, pos);
		if (node->committed)
			continue;

		git_refdb_unlock(tx->db, node->payload, false, false, NULL, NULL, NULL);
	}

	git_refdb_free(tx->db);
	git_strmap_free(tx->locks);

	/* tx is inside the pool, so we need to extract the data */
	memcpy(&pool, &tx->pool, sizeof(git_pool));
	git_pool_clear(&pool);
}
