package git

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

type ErrorClass int

const (
	ErrClassNone       ErrorClass = C.GITERR_NONE
	ErrClassNoMemory              = C.GITERR_NOMEMORY
	ErrClassOs                    = C.GITERR_OS
	ErrClassInvalid               = C.GITERR_INVALID
	ErrClassReference             = C.GITERR_REFERENCE
	ErrClassZlib                  = C.GITERR_ZLIB
	ErrClassRepository            = C.GITERR_REPOSITORY
	ErrClassConfig                = C.GITERR_CONFIG
	ErrClassRegex                 = C.GITERR_REGEX
	ErrClassOdb                   = C.GITERR_ODB
	ErrClassIndex                 = C.GITERR_INDEX
	ErrClassObject                = C.GITERR_OBJECT
	ErrClassNet                   = C.GITERR_NET
	ErrClassTag                   = C.GITERR_TAG
	ErrClassTree                  = C.GITERR_TREE
	ErrClassIndexer               = C.GITERR_INDEXER
	ErrClassSSL                   = C.GITERR_SSL
	ErrClassSubmodule             = C.GITERR_SUBMODULE
	ErrClassThread                = C.GITERR_THREAD
	ErrClassStash                 = C.GITERR_STASH
	ErrClassCheckout              = C.GITERR_CHECKOUT
	ErrClassFetchHead             = C.GITERR_FETCHHEAD
	ErrClassMerge                 = C.GITERR_MERGE
	ErrClassSsh                   = C.GITERR_SSH
	ErrClassFilter                = C.GITERR_FILTER
	ErrClassRevert                = C.GITERR_REVERT
	ErrClassCallback              = C.GITERR_CALLBACK
)

type ErrorCode int

const (

	// No error
	ErrOk ErrorCode = C.GIT_OK
	// Generic error
	ErrGeneric = C.GIT_ERROR
	// Requested object could not be found
	ErrNotFound = C.GIT_ENOTFOUND
	// Object exists preventing operation
	ErrExists = C.GIT_EEXISTS
	// More than one object matches
	ErrAmbigious = C.GIT_EAMBIGUOUS
	// Output buffer too short to hold data
	ErrBuffs = C.GIT_EBUFS
	// GIT_EUSER is a special error that is never generated by libgit2
	// code.  You can return it from a callback (e.g to stop an iteration)
	// to know that it was generated by the callback and not by libgit2.
	ErrUser = C.GIT_EUSER
	// Operation not allowed on bare repository
	ErrBareRepo = C.GIT_EBAREREPO
	// HEAD refers to branch with no commits
	ErrUnbornBranch = C.GIT_EUNBORNBRANCH
	// Merge in progress prevented operation
	ErrUnmerged = C.GIT_EUNMERGED
	// Reference was not fast-forwardable
	ErrNonFastForward = C.GIT_ENONFASTFORWARD
	// Name/ref spec was not in a valid format
	ErrInvalidSpec = C.GIT_EINVALIDSPEC
	// Merge conflicts prevented operation
	ErrMergeConflict = C.GIT_EMERGECONFLICT
	// Lock file prevented operation
	ErrLocked = C.GIT_ELOCKED
	// Reference value does not match expected
	ErrModified = C.GIT_EMODIFIED
	// Internal only
	ErrPassthrough = C.GIT_PASSTHROUGH
	// Signals end of iteration with iterator
	ErrIterOver = C.GIT_ITEROVER
)

var (
	ErrInvalid = errors.New("Invalid state for operation")
)

func init() {
	C.git_threads_init()
}

// Oid represents the id for a Git object.
type Oid [20]byte

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

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

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

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

func NewOid(s string) (*Oid, error) {
	if len(s) > C.GIT_OID_HEXSZ {
		return nil, errors.New("string is too long for oid")
	}

	o := new(Oid)

	slice, error := hex.DecodeString(s)
	if error != nil {
		return nil, error
	}

	if len(slice) != 20 {
		return nil, &GitError{"Invalid Oid", ErrClassNone, ErrGeneric}
	}

	copy(o[:], slice[:20])
	return o, nil
}

func (oid *Oid) String() string {
	return hex.EncodeToString(oid[:])
}

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

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

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

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

func (oid *Oid) NCmp(oid2 *Oid, n uint) int {
	return bytes.Compare(oid[:n], oid2[: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

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	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), MakeGitError(ret)
		}
	}
	return int(ret), nil
}

type GitError struct {
	Message string
	Class   ErrorClass
	Code    ErrorCode
}

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

func IsErrorClass(err error, c ErrorClass) bool {

	if err == nil {
		return false
	}
	if gitError, ok := err.(*GitError); ok {
		return gitError.Class == c
	}
	return false
}

func IsErrorCode(err error, c ErrorCode) bool {
	if err == nil {
		return false
	}
	if gitError, ok := err.(*GitError); ok {
		return gitError.Code == c
	}
	return false
}

func MakeGitError(errorCode C.int) error {

	var errMessage string
	var errClass ErrorClass
	if errorCode != ErrIterOver {
		err := C.giterr_last()
		if err != nil {
			errMessage = C.GoString(err.message)
			errClass = ErrorClass(err.klass)
		} else {
			errClass = ErrClassInvalid
		}
	}
	return &GitError{errMessage, errClass, ErrorCode(errorCode)}
}

func MakeGitError2(err int) error {
	return MakeGitError(C.int(err))
}

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))

	var buf C.git_buf
	defer C.git_buf_free(&buf)

	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	ret := C.git_repository_discover(&buf, cstart, cbool(across_fs), ceildirs)
	if ret < 0 {
		return "", MakeGitError(ret)
	}

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