package git

/*
#include <git2.h>
*/
import "C"
import (
	"runtime"
	"unsafe"
)

// DescribeOptions represents the describe operation configuration.
//
// You can use DefaultDescribeOptions() to get default options.
type DescribeOptions struct {
	// How many tags as candidates to consider to describe the input commit-ish.
	// Increasing it above 10 will take slightly longer but may produce a more
	// accurate result. 0 will cause only exact matches to be output.
	MaxCandidatesTags uint // default: 10

	// By default describe only shows annotated tags. Change this in order
	// to show all refs from refs/tags or refs/.
	Strategy DescribeOptionsStrategy // default: DescribeDefault

	// Only consider tags matching the given glob(7) pattern, excluding
	// the "refs/tags/" prefix. Can be used to avoid leaking private
	// tags from the repo.
	Pattern string

	// When calculating the distance from the matching tag or
	// reference, only walk down the first-parent ancestry.
	OnlyFollowFirstParent bool

	// If no matching tag or reference is found, the describe
	// operation would normally fail. If this option is set, it
	// will instead fall back to showing the full id of the commit.
	ShowCommitOidAsFallback bool
}

// DefaultDescribeOptions returns default options for the describe operation.
func DefaultDescribeOptions() (DescribeOptions, error) {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	opts := C.git_describe_options{}
	ecode := C.git_describe_init_options(&opts, C.GIT_DESCRIBE_OPTIONS_VERSION)
	if ecode < 0 {
		return DescribeOptions{}, MakeGitError(ecode)
	}

	return DescribeOptions{
		MaxCandidatesTags: uint(opts.max_candidates_tags),
		Strategy:          DescribeOptionsStrategy(opts.describe_strategy),
	}, nil
}

// DescribeFormatOptions can be used for formatting the describe string.
//
// You can use DefaultDescribeFormatOptions() to get default options.
type DescribeFormatOptions struct {
	// Size of the abbreviated commit id to use. This value is the
	// lower bound for the length of the abbreviated string.
	AbbreviatedSize uint // default: 7

	// Set to use the long format even when a shorter name could be used.
	AlwaysUseLongFormat bool

	// If the workdir is dirty and this is set, this string will be
	// appended to the description string.
	DirtySuffix string
}

// DefaultDescribeFormatOptions returns default options for formatting
// the output.
func DefaultDescribeFormatOptions() (DescribeFormatOptions, error) {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	opts := C.git_describe_format_options{}
	ecode := C.git_describe_init_format_options(&opts, C.GIT_DESCRIBE_FORMAT_OPTIONS_VERSION)
	if ecode < 0 {
		return DescribeFormatOptions{}, MakeGitError(ecode)
	}

	return DescribeFormatOptions{
		AbbreviatedSize:     uint(opts.abbreviated_size),
		AlwaysUseLongFormat: opts.always_use_long_format == 1,
	}, nil
}

// DescribeOptionsStrategy behaves like the --tags and --all options
// to git-describe, namely they say to look for any reference in
// either refs/tags/ or refs/ respectively.
//
// By default it only shows annotated tags.
type DescribeOptionsStrategy uint

// Describe strategy options.
const (
	DescribeDefault DescribeOptionsStrategy = C.GIT_DESCRIBE_DEFAULT
	DescribeTags    DescribeOptionsStrategy = C.GIT_DESCRIBE_TAGS
	DescribeAll     DescribeOptionsStrategy = C.GIT_DESCRIBE_ALL
)

// Describe performs the describe operation on the commit.
func (c *Commit) Describe(opts *DescribeOptions) (*DescribeResult, error) {
	var resultPtr *C.git_describe_result

	var cDescribeOpts *C.git_describe_options
	if opts != nil {
		var cpattern *C.char
		if len(opts.Pattern) > 0 {
			cpattern = C.CString(opts.Pattern)
			defer C.free(unsafe.Pointer(cpattern))
		}

		cDescribeOpts = &C.git_describe_options{
			version:                     C.GIT_DESCRIBE_OPTIONS_VERSION,
			max_candidates_tags:         C.uint(opts.MaxCandidatesTags),
			describe_strategy:           C.uint(opts.Strategy),
			pattern:                     cpattern,
			only_follow_first_parent:    cbool(opts.OnlyFollowFirstParent),
			show_commit_oid_as_fallback: cbool(opts.ShowCommitOidAsFallback),
		}
	}

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_describe_commit(&resultPtr, c.ptr, cDescribeOpts)
	runtime.KeepAlive(c)
	if ecode < 0 {
		return nil, MakeGitError(ecode)
	}

	return newDescribeResultFromC(resultPtr), nil
}

// DescribeWorkdir describes the working tree. It means describe HEAD
// and appends <mark> (-dirty by default) if the working tree is dirty.
func (repo *Repository) DescribeWorkdir(opts *DescribeOptions) (*DescribeResult, error) {
	var resultPtr *C.git_describe_result

	var cDescribeOpts *C.git_describe_options
	if opts != nil {
		var cpattern *C.char
		if len(opts.Pattern) > 0 {
			cpattern = C.CString(opts.Pattern)
			defer C.free(unsafe.Pointer(cpattern))
		}

		cDescribeOpts = &C.git_describe_options{
			version:                     C.GIT_DESCRIBE_OPTIONS_VERSION,
			max_candidates_tags:         C.uint(opts.MaxCandidatesTags),
			describe_strategy:           C.uint(opts.Strategy),
			pattern:                     cpattern,
			only_follow_first_parent:    cbool(opts.OnlyFollowFirstParent),
			show_commit_oid_as_fallback: cbool(opts.ShowCommitOidAsFallback),
		}
	}

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_describe_workdir(&resultPtr, repo.ptr, cDescribeOpts)
	runtime.KeepAlive(repo)
	if ecode < 0 {
		return nil, MakeGitError(ecode)
	}

	return newDescribeResultFromC(resultPtr), nil
}

// DescribeResult represents the output from the 'git_describe_commit'
// and 'git_describe_workdir' functions in libgit2.
//
// Use Format() to get a string out of it.
type DescribeResult struct {
	ptr *C.git_describe_result
}

func newDescribeResultFromC(ptr *C.git_describe_result) *DescribeResult {
	result := &DescribeResult{
		ptr: ptr,
	}
	runtime.SetFinalizer(result, (*DescribeResult).Free)
	return result
}

// Format prints the DescribeResult as a string.
func (result *DescribeResult) Format(opts *DescribeFormatOptions) (string, error) {
	resultBuf := C.git_buf{}

	var cFormatOpts *C.git_describe_format_options
	if opts != nil {
		cDirtySuffix := C.CString(opts.DirtySuffix)
		defer C.free(unsafe.Pointer(cDirtySuffix))

		cFormatOpts = &C.git_describe_format_options{
			version:                C.GIT_DESCRIBE_FORMAT_OPTIONS_VERSION,
			abbreviated_size:       C.uint(opts.AbbreviatedSize),
			always_use_long_format: cbool(opts.AlwaysUseLongFormat),
			dirty_suffix:           cDirtySuffix,
		}
	}

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ecode := C.git_describe_format(&resultBuf, result.ptr, cFormatOpts)
	runtime.KeepAlive(result)
	if ecode < 0 {
		return "", MakeGitError(ecode)
	}
	defer C.git_buf_free(&resultBuf)

	return C.GoString(resultBuf.ptr), nil
}

// Free cleans up the C reference.
func (result *DescribeResult) Free() {
	runtime.SetFinalizer(result, nil)
	C.git_describe_result_free(result.ptr)
	result.ptr = nil
}
