package git

/*
#cgo pkg-config: libgit2
#include <git2.h>
#include <git2/errors.h>
*/
import "C"
import (
	"bytes"
	"errors"
	"unsafe"
	"strings"
)

const (
	ITEROVER  = C.GIT_ITEROVER
	EEXISTS   = C.GIT_EEXISTS
	ENOTFOUND = C.GIT_ENOTFOUND
)

var (
	ErrIterOver = errors.New("Iteration is over")
)

func init() {
	C.git_threads_init()
}

// Oid
type Oid struct {
	bytes [20]byte
}

func newOidFromC(coid *C.git_oid) *Oid {
	if coid == nil {
		return nil
	}

	oid := new(Oid)
	copy(oid.bytes[0:20], C.GoBytes(unsafe.Pointer(coid), 20))
	return oid
}

func CopyOid(oid *Oid, coid *C.git_oid) {
	copy(oid.bytes[0:20], C.GoBytes(unsafe.Pointer(coid), 20))
}

func NewOid(b []byte) *Oid {
	oid := new(Oid)
	copy(oid.bytes[0:20], b[0:20])
	return oid
}

func (oid *Oid) toC() *C.git_oid {
	return (*C.git_oid)(unsafe.Pointer(&oid.bytes))
}

func NewOidFromString(s string) (*Oid, error) {
	o := new(Oid)
	cs := C.CString(s)
	defer C.free(unsafe.Pointer(cs))

	if C.git_oid_fromstr(o.toC(), cs) < 0 {
		return nil, LastError()
	}

	return o, nil
}

func (oid *Oid) String() string {
	buf := make([]byte, 40)
	C.git_oid_fmt((*C.char)(unsafe.Pointer(&buf[0])), oid.toC())
	return string(buf)
}

func (oid *Oid) Bytes() []byte {
	return oid.bytes[0:]
}

func (oid *Oid) Cmp(oid2 *Oid) int {
	return bytes.Compare(oid.bytes[:], oid2.bytes[:])
}

func (oid *Oid) Copy() *Oid {
	ret := new(Oid)
	copy(ret.bytes[:], oid.bytes[:])
	return ret
}

func (oid *Oid) Equal(oid2 *Oid) bool {
	return bytes.Equal(oid.bytes[:], oid2.bytes[:])
}

func (oid *Oid) IsZero() bool {
	for _, a := range(oid.bytes) {
		if a != '0' {
			return false
		}
	}
	return true
}

func (oid *Oid) NCmp(oid2 *Oid, n uint) int {
	return bytes.Compare(oid.bytes[:n], oid2.bytes[:n])
}

func ShortenOids(ids []*Oid, minlen int) (int, error) {
	shorten := C.git_oid_shorten_new(C.size_t(minlen))
	if shorten == nil {
		panic("Out of memory")
	}
	defer C.git_oid_shorten_free(shorten)

	var ret C.int
	for _, id := range ids {
		buf := make([]byte, 41)
		C.git_oid_fmt((*C.char)(unsafe.Pointer(&buf[0])), id.toC())
		buf[40] = 0
		ret = C.git_oid_shorten_add(shorten, (*C.char)(unsafe.Pointer(&buf[0])))
		if ret < 0 {
			return int(ret), LastError()
		}
	}
	return int(ret), nil
}

type GitError struct {
	Message string
	Code int
}

func (e GitError) Error() string{
	return e.Message
}

func LastError() error {
	err := C.giterr_last()
	if err == nil {
		return &GitError{"No message", 0}
	}
	return &GitError{C.GoString(err.message), int(err.klass)}
}

func cbool(b bool) C.int {
	if (b) {
		return C.int(1)
	}
	return C.int(0)
}

func ucbool(b bool) C.uint {
	if (b) {
		return C.uint(1)
	}
	return C.uint(0)
}

func Discover(start string, across_fs bool, ceiling_dirs []string) (string, error) {
	ceildirs := C.CString(strings.Join(ceiling_dirs, string(C.GIT_PATH_LIST_SEPARATOR)))
	defer C.free(unsafe.Pointer(ceildirs))

	cstart := C.CString(start)
	defer C.free(unsafe.Pointer(cstart))

	retpath := (*C.char)(C.malloc(C.GIT_PATH_MAX))
	defer C.free(unsafe.Pointer(retpath))

	r := C.git_repository_discover(retpath, C.GIT_PATH_MAX, cstart, cbool(across_fs), ceildirs)

	if r == 0 {
		return C.GoString(retpath), nil
	}

	return "", LastError()
}
