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.gitObject.ptr, cDescribeOpts)
	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)
	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)
	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
}
