package main

import "C"
import (
	"Sunny/CertificateManager"
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"io/ioutil"
	"os"
	"sync"
	"unsafe"
)

var ContextIDL sync.Mutex
var ContextMap = make(map[int]int)
var ContextID int
var CertificateLock sync.Mutex

func GetContextID(Context int) int {
	//	return Context - prtAddr
	ContextIDL.Lock()
	defer ContextIDL.Unlock()
	if ContextMap[Context] > 10000 {
		return ContextMap[Context]
	}
	ContextID++
	X := ContextID
	if X < 10001 || X > 2147483647 {
		X = 10001
		ContextID = 10001
	}

	ContextMap[Context] = X
	return X
}

type SyCer struct {
	tls          *tls.Config
	PrivateKey   string
	Certificates string
}

var CertificateMap = make(map[int]*SyCer)

//export CreateCertificate
//创建 证书管理器 对象
func CreateCertificate() int {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	w := &SyCer{tls: &tls.Config{}}
	i := int(uintptr(unsafe.Pointer(w)))
	Context := GetContextID(i)
	CertificateMap[Context] = w
	return Context
}

//export RemoveCertificate
//释放 证书管理器 对象
func RemoveCertificate(Context int) {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return
	}
	c = nil
	delete(CertificateMap, Context)
}
func LoadCertificateContext(Context int) *SyCer {
	s := CertificateMap[Context]
	if s == nil {
		return nil
	}
	return s
}

//export LoadP12Certificate
//证书管理器 载入p12证书
func LoadP12Certificate(Context int, Name, Password *C.char) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}
	p, Certificates, private, e := CertificateManager.AddP12Certificate(AuthCharUTF8(Name), AuthCharUTF8(Password))
	if e != nil {
		return false
	}
	c.PrivateKey = private
	c.Certificates = Certificates
	c.tls.Certificates = []tls.Certificate{*p}
	return true
}

//export LoadX509KeyPair
//证书管理器 载入X509证书2
func LoadX509KeyPair(Context int, Ca_Path, KEY_Path *C.char) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}
	keyPEMBlock, err := os.ReadFile(AuthCharUTF8(KEY_Path))
	if err != nil {
		return false
	}
	CaPEMBlock, err := os.ReadFile(AuthCharUTF8(Ca_Path))
	if err != nil {
		return false
	}
	c.PrivateKey = string(keyPEMBlock)
	c.Certificates = string(CaPEMBlock)
	ok, p := CertificateManager.LoadX509KeyPair(AuthCharUTF8(Ca_Path), AuthCharUTF8(KEY_Path))
	if ok == false {
		return false
	}
	c.tls.Certificates = []tls.Certificate{*p}
	return true
}

//export LoadX509Certificate
//证书管理器 载入X509证书1
func LoadX509Certificate(Context int, Host, CA, KEY *C.char) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}
	c.PrivateKey = AuthCharUTF8(KEY)
	c.Certificates = AuthCharUTF8(CA)
	ok, p := CertificateManager.LoadX509Certificate(AuthCharUTF8(Host), []byte(AuthCharUTF8(CA)), []byte(c.PrivateKey))
	if ok == false {
		return false
	}
	c.tls.Certificates = []tls.Certificate{*p}
	return true
}

//export SetInsecureSkipVerify
//证书管理器 设置跳过主机验证
func SetInsecureSkipVerify(Context int, b bool) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}
	c.tls.InsecureSkipVerify = b
	return true
}

//export SetServerName
//证书管理器 设置ServerName
func SetServerName(Context int, name *C.char) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}
	c.tls.ServerName = AuthCharUTF8(name)
	return true
}

//export GetServerName
//证书管理器 取ServerName
func GetServerName(Context int) uintptr {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return 0
	}
	if c.tls == nil {
		return 0
	}
	var bs bytes.Buffer
	bs.WriteString(c.tls.ServerName)
	bs.Write([]byte{0})
	B := bs.Bytes()
	if len(B) < 1 {
		return 0
	}
	return uintptr(unsafe.Pointer(&B[0]))
}

//export AddCertPoolPath
//证书管理器 设置信任的证书 从 文件
func AddCertPoolPath(Context int, cer *C.char) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}
	if c.tls.ClientCAs == nil {
		c.tls.ClientCAs = x509.NewCertPool()
	}
	if addTrust(c.tls.ClientCAs, AuthCharUTF8(cer)) != nil {
		return false
	}

	return true
}

//export AddCertPoolText
//证书管理器 设置信任的证书 从 文本
func AddCertPoolText(Context int, cer *C.char) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}
	if c.tls.ClientCAs == nil {
		c.tls.ClientCAs = x509.NewCertPool()
	}
	c.tls.ClientCAs.AppendCertsFromPEM([]byte(AuthCharUTF8(cer)))
	return true
}

//export AddClientAuth
//证书管理器 设置ClientAuth
func AddClientAuth(Context, val int) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}
	switch val {
	case 0:
		c.tls.ClientAuth = tls.NoClientCert
		break
	case 1:
		c.tls.ClientAuth = tls.RequestClientCert
		break
	case 2:
		c.tls.ClientAuth = tls.RequireAnyClientCert
		break
	case 3:
		c.tls.ClientAuth = tls.VerifyClientCertIfGiven
		break
	case 4:
		c.tls.ClientAuth = tls.RequireAndVerifyClientCert
		break
	default:
		c.tls.ClientAuth = tls.NoClientCert
		break
	}
	return true
}
func addTrust(pool *x509.CertPool, path string) error {
	aCrt, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	pool.AppendCertsFromPEM(aCrt)
	return nil
}

//export CreateCA
//证书管理器 创建证书
func CreateCA(Context int, Country, Organization, OrganizationalUnit, Province, CommonName, Locality *C.char, bits, NotAfter int) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return false
	}
	if c.tls == nil {
		return false
	}

	a, b, e := CertificateManager.CreateCA(
		AuthCharUTF8(Country),
		AuthCharUTF8(Organization),
		AuthCharUTF8(OrganizationalUnit),
		AuthCharUTF8(Province),
		AuthCharUTF8(CommonName),
		AuthCharUTF8(Locality),
		bits,
		NotAfter)
	c.PrivateKey = string(b)
	c.Certificates = string(a)
	if e != nil {
		return false
	}
	ok, p := CertificateManager.LoadX509Certificate(AuthCharUTF8(CommonName), a, b)
	if ok == false {
		return false
	}
	c.tls.Certificates = []tls.Certificate{*p}
	return true
}

//export ExportCA
//证书管理器 导出证书
func ExportCA(Context int) uintptr {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	var B bytes.Buffer
	B.Write([]byte(_ExportCA(Context)))
	B.Write([]byte{0})
	I := B.Bytes()
	return uintptr(unsafe.Pointer(&I[0]))
}
func _ExportCA(Context int) string {
	c := LoadCertificateContext(Context)
	if c == nil {
		return ""
	}
	return c.Certificates
	/*
		if c.tls == nil {
			return ""
		}
		if c.tls.Certificates == nil {
			return ""
		}
		if len(c.tls.Certificates) < 1 {
			return ""
		}
		if len(c.tls.Certificates[0].Certificate) < 1 {
			return ""
		}
		rootCert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: c.tls.Certificates[0].Certificate[0]})
		return string(rootCert)
	*/
}

//export ExportKEY
//证书管理器 导出私钥
func ExportKEY(Context int) uintptr {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return 0
	}
	var B bytes.Buffer
	B.Write([]byte(c.PrivateKey))
	B.Write([]byte{0})
	I := B.Bytes()
	return uintptr(unsafe.Pointer(&I[0]))
}
func _ExportKEY(Context int) string {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return ""
	}

	return c.PrivateKey
}

//export ExportPub
//证书管理器 导出公钥
func ExportPub(Context int) uintptr {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := LoadCertificateContext(Context)
	if c == nil {
		return 0
	}
	k := c.PrivateKey
	if k == "" {
		return 0
	}
	p, _ := pem.Decode([]byte(k))
	if p == nil {
		return 0
	}
	Key, err := x509.ParsePKCS1PrivateKey(p.Bytes)
	if err != nil {
		return 0
	}
	pubs, err := x509.MarshalPKIXPublicKey(&Key.PublicKey)
	if err != nil {
		return 0
	}
	rootPub := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: pubs})
	var B bytes.Buffer
	B.Write(rootPub)
	B.Write([]byte{0})
	I := B.Bytes()
	return uintptr(unsafe.Pointer(&I[0]))

}

//export ExportP12
//证书管理器 导出为P12
func ExportP12(Context int, path, pass *C.char) bool {
	CertificateLock.Lock()
	defer CertificateLock.Unlock()
	c := _ExportCA(Context)
	cc := LoadCertificateContext(Context)
	if cc == nil {
		return false
	}
	k := cc.PrivateKey
	if c == "" || k == "" {
		return false
	}
	pwd := AuthCharUTF8(pass)
	b, e := CertificateManager.CertToP12(c, k, pwd)
	if e != nil {
		return false
	}
	e = WriteBytestoFile(b, AuthCharUTF8(path))
	return e == nil
}
