package genji


/*
#cgo LDFLAGS:  -L . -l genji
#include <stdlib.h>
#include "genji.h"
*/
import (
	"C"
)

import  "unsafe"

func Init_MatrixAPI() (ret int16) {

	ret = int16(C.Init_MatrixAPI())
	return
}

func Release_MatrixAPI() (ret int16) {

	ret = int16(C.Release_MatrixAPI())
	return
}

func GetVersionAPI() (ret int32) {
	ret = int32(C.GetVersionAPI())
	return
}

func GetVersionDRV() (ret int32) {
	ret = int32(C.GetVersionDRV())
	return
}

func GetVersionDRV_USB() (ret int32) {
	ret = int32(C.GetVersionDRV_USB())
	return
}

func Dongle_Version(DngNr int16) (ret int32) {
	ret = int32(C.Dongle_Version(C.short(DngNr), 85))
	return
}

func Dongle_Model(DngNr int16) (ret int32) {
	ret = int32(C.Dongle_Model(C.short(DngNr), 85))
	return
}

func Dongle_MemSize(DngNr int16) (ret int16) {
	ret = int16(C.Dongle_MemSize(C.short(DngNr), 85))
	return
}

func Dongle_Count() (ret int16) {

	ret = int16(C.Dongle_Count(85))
	return
}

func Dongle_ReadSerNr(UserCode int32, DngNr int16) (ret int32) {

	ret = int32(C.Dongle_ReadSerNr(C.int(UserCode), C.short(DngNr), 85))
	return
}

func Dongle_ReadData(UserCode int32, Data []int32, Count int16, DngNr int16) (ret int16) {

	ret = int16(C.Dongle_ReadData(C.int(UserCode), (*C.int)(&Data[0]), C.short(Count), C.short(DngNr), 85))
	return
}

func Dongle_ReadDataEx(UserCode int32, Data []int32, Fpos int16, Count int16, DngNr int16) (ret int16) {

	ret = int16(C.Dongle_ReadDataEx(C.int(UserCode), (*C.int)(&Data[0]), C.short(Fpos), C.short(Count), C.short(DngNr), 85))
	return
}

func Dongle_GetKeyFlag(UserCode int32, DngNr int16) (ret int16) {
	ret = int16(C.Dongle_GetKeyFlag(C.int(UserCode), C.short(DngNr), 85))
	return
}

func Dongle_EncryptData(UserCode int32, DataBlock []int32, DngNr int16) (ret int16) {
	ret = int16(C.Dongle_EncryptData(C.int(UserCode), (*C.int)(&DataBlock[0]), C.short(DngNr), 85))
	return
}

func Dongle_DecryptData(UserCode int32, DataBlock []int32, DngNr int16) (ret int16) {
	ret = int16(C.Dongle_DecryptData(C.int(UserCode), (*C.int)(&DataBlock[0]), C.short(DngNr), 85))
	return
}

func MxApp_Encrypt(Data *[2]uint32, Key [4]uint32) int16 {
	var delta, sum uint32
	var cnt int16

	sum = 0
	delta = 0x9E3779B9
	cnt = 32
	for cnt = 32; cnt > 0; cnt-- {
		Data[0] += ((Data[1]<<4 ^ Data[1]>>5) + Data[1]) ^ (sum + Key[sum&3])
		sum += delta
		Data[1] += ((Data[0]<<4 ^ Data[0]>>5) + Data[0]) ^ (sum + Key[sum>>11&3])
	}
	return 0
}

func MxApp_Decrypt(Data *[2]uint32, Key [4]uint32) int16 {
	var delta, sum uint32
	var cnt int16

	sum = 0xC6EF3720
	delta = 0x9E3779B9
	cnt = 32
	for cnt = 32; cnt > 0; cnt-- {
		Data[1] -= ((Data[0]<<4 ^ Data[0]>>5) + Data[0]) ^ (sum + Key[sum>>11&3])
		sum -= delta
		Data[0] -= ((Data[1]<<4 ^ Data[1]>>5) + Data[1]) ^ (sum + Key[sum&3])
	}
	return 0
}

func Dongle_SetLED(mode int16, dNr int16) (ret int16) {
	ret = int16(C.Dongle_SetLED(C.short(mode), C.short(dNr), 85))
	return
}

func Dongle_GetRand(UserCode int32, siz int16, pRand []byte, dNr int16) (ret int16) {
	ret = int16(C.Dongle_GetRand(C.int(UserCode), C.short(siz), (*C.uchar)(unsafe.Pointer(&pRand[0])), C.short(dNr), 85))
	return
}

func Dongle_ReadGUSN( UserCode int32, gSN []byte,  dNr int16) ( ret int16){
	ret = int16(C.Dongle_ReadGUSN(C.int(UserCode), (*C.uchar)(unsafe.Pointer(&gSN[0])), C.short(dNr), 85))
	return
}

func Dongle_MemSize2( dNr int16)(ret int16) {
	ret = int16(C.Dongle_MemSize2(C.short(dNr), C.short(85)))
	return
}

func Dongle_WriteData2( UserCode int32,  data []byte,  pos int16, len uint16, dNr int16)(ret int16) {
	ret = int16( C.Dongle_WriteData2(C.int(UserCode), (*C.uchar)(&data[0]), C.ushort(pos), C.ushort(len), C.short(dNr), C.short(85)))
	return
}

func Dongle_ReadData2(UserCode int32, data []byte, pos uint16,len uint16,dNr int16)(ret int16) {
	ret = int16( C.Dongle_ReadData2(C.int(UserCode), (*C.uchar)(unsafe.Pointer(&data[0])), C.ushort(pos), C.ushort(len), C.short(dNr), C.short(85)) )
	return
}

func Dongle_LockData2(UserCode int32, bLock int, lockKey uint32,dNr int16)(ret int16) {
	ret = int16( C.Dongle_LockData2(C.int(UserCode), C.int(bLock), C.uint(lockKey), C.short(dNr), C.short(85)))
	return
}

func Dongle_LockData(UserCode int32, bLock int, lockKey uint32,dNr int16)(ret int16) {
	ret = int16( C.Dongle_LockData(C.int(UserCode), C.int(bLock), C.uint(lockKey), C.short(dNr), C.short(85)))
	return
}

func Dongle_CreateRSAKeyPair( UserCode int32, idx int16, dNr int16 ) (ret int16){
	ret = int16(C.Dongle_CreateRSAKeyPair( C.int(UserCode), C.short(idx), C.short(dNr), C.short(85)) )
	return
}

func Dongle_WriteRSAKey( UserCode int32, idx int16, bPrivKey int, keySize int16, pKeyBuf []byte, dNr int16)(ret int16) {
	ret = int16(C.Dongle_WriteRSAKey(C.int(UserCode), C.short(idx), C.int(bPrivKey), C.ushort(keySize), (*C.uchar)(&pKeyBuf[0]), C.short(dNr), C.short(85)))
	return
}

func Dongle_LockRSAKeyPair( UserCode int32, idx int16, bLock int, lockKey uint32, dNr int16 )(ret int16) {
	ret = int16(C.Dongle_LockRSAKeyPair(C.int(UserCode), C.short(idx), C.int(bLock), C.uint(lockKey), C.short(dNr), C.short(85)))
	return
}

func Dongle_EncryptDataRSA( UserCode int32, idx int16,  plainText []byte, plainTextLen int16, cipher []byte, cipherLen *int16, dNr int16) (ret int16 ){
	ret = int16(C.Dongle_EncryptDataRSA( C.int(UserCode), C.short(idx), (*C.uchar)(&plainText[0]), C.short(plainTextLen), (*C.uchar)(unsafe.Pointer(&cipher[0])), (*C.short)(cipherLen), C.short(dNr), C.short(85)))
	return 
}

func Dongle_DecryptDataRSA( UserCode int32, idx int16, cipher []byte, cipherLen int16, plainText []byte, plainTextLen *int16, dNr int16 ) (ret int16) {
	ret = int16(C.Dongle_DecryptDataRSA( C.int(UserCode), C.short(idx), (*C.uchar)(&cipher[0]), C.short(cipherLen), (*C.uchar)(unsafe.Pointer(&plainText[0])), (*C.short)(plainTextLen), C.short(dNr), C.short(85)))
	return 
}

func Dongle_SignDataRSA( UserCode int32, idx int16, msg []byte, msgLen int16,  sigData []byte, sigLen *int16,dNr int16)(ret int16) {
	ret = int16(C.Dongle_SignDataRSA( C.int(UserCode), C.short(idx), (*C.uchar)(&msg[0]), C.short(msgLen), (*C.uchar)(unsafe.Pointer(&sigData[0])), (*C.short)(sigLen), C.short(dNr), C.short(85)))
	return 
}

func Dongle_VerifySigRSA(UserCode int32,idx int16,msg []byte, msgLen int16,sigData []byte, sigLen int16, dNr int16)(ret int16) {
	ret = int16(C.Dongle_VerifySigRSA( C.int(UserCode), C.short(idx), (*C.uchar)(&msg[0]), C.short(msgLen), (*C.uchar)(&sigData[0]), (C.short)(sigLen), C.short(dNr), C.short(85)))
	return 
}

func Dongle_SetTimer(UserCode int32, mode int16, dNr int16 )(ret int16){
	ret = int16(C.Dongle_SetTimer(C.int(UserCode),C.short(mode), C.short(dNr), C.short(85)))
	return
}

func Dongle_StartTimer(UserCode int32, dNr int16) (ret int16){
	ret = int16(C.Dongle_StartTimer(C.int(UserCode),C.short(dNr), C.short(85)))
	return
}

func Dongle_GetTimer(UserCode int32, dwCount *uint32,  dNr int16)(ret int16){
	ret = int16(C.Dongle_GetTimer(C.int(UserCode),(*C.uint)(dwCount), C.short(dNr), C.short(85)))
	return
}

func Dongle_StopTimer(UserCode int32, dNr int16)(ret int16){
	ret = int16(C.Dongle_StopTimer(C.int(UserCode),C.short(dNr), C.short(85)))
	return
}

func Dongle_GetRSAPubKey( UserCode int32,idx int16,pubKey []byte, pubKeyLen *int16, dNr int16 )(ret int16){
	ret = int16(C.Dongle_GetRSAPubKey( C.int(UserCode), C.short(idx), (*C.uchar)(unsafe.Pointer(&pubKey[0])), (*C.short)(pubKeyLen), C.short(dNr), C.short(85)))
	return 
}

func EncryptByCOSRsaPubKey(pubKey []byte, pubKey_len int16, plainText []byte, plainTextLen int16, cipher []byte, cipherLen *int16)(ret int16){
	ret = int16(C.EncryptByCOSRsaPubKey( (*C.uchar)(&pubKey[0]), C.short(pubKey_len),(*C.uchar)(&plainText[0]), C.short(plainTextLen), (*C.uchar)(unsafe.Pointer(&cipher[0])), (*C.short)(cipherLen)))
	return 
}

func Dongle_WriteKeyHMACSHA1( UserCode int32, key []byte, dNr int16 )(ret int16){
	//key must be at least 25 bytes long
	if len(key) < 25 {
		return -1
	}
	ret = int16(C.Dongle_WriteKeyHMACSHA1( C.int(UserCode), (*C.uchar)(&key[0]), C.short(dNr), C.short(85)))
	return 
}

func Dongle_HMACSHA1( UserCode int32, plainText []byte, plainLen int16, hash []byte, hashLen *int16, dNr int16 )(ret int16){
	ret = int16(C.Dongle_HMACSHA1( C.int(UserCode), (*C.uchar)(&plainText[0]), C.short(plainLen),(*C.uchar)(unsafe.Pointer(&hash[0])), (*C.short)(hashLen), C.short(dNr), C.short(85)))
	return 
}

func RegisterGenjiCallbackPort( port int  ){
	C.RegisterGenjiCallbackPort( C.int(port) )
	return
}

