package main

import "C"
import (
	"sync"
	"unsafe"
)

var Queue = make(map[string]*ArrayQueue)
var QueueLock sync.Mutex

type ArrayQueue struct {
	Array [][]byte
	Size  int
	Lock  sync.Mutex
}

//export CreateQueue
//创建队列
func CreateQueue(name *C.char) {
	str := C.GoString(name)
	QueueLock.Lock()
	if Queue[str] == nil {
		Queue[str] = new(ArrayQueue)
	} else {
		Queue[str].Empty()
	}
	QueueLock.Unlock()
	return
}

//export QueueIsEmpty
//队列是否为空
func QueueIsEmpty(name *C.char) bool {
	str := C.GoString(name)
	QueueLock.Lock()
	Object := Queue[str]
	QueueLock.Unlock()
	if Object == nil {
		return true
	}
	return Object.IsEmpty()
}

//export QueueRelease
//清空销毁队列
func QueueRelease(name *C.char) {
	str := C.GoString(name)
	QueueLock.Lock()
	Object := Queue[str]
	QueueLock.Unlock()
	if Object == nil {
		return
	}
	Object.Empty()
	QueueLock.Lock()
	delete(Queue, str)
	QueueLock.Unlock()
}

//export QueueLength
//取队列长度
func QueueLength(name *C.char) int {
	str := C.GoString(name)
	QueueLock.Lock()
	Object := Queue[str]
	QueueLock.Unlock()
	if Object == nil {
		return 0
	}
	return Object.Length()
}

//export QueuePush
//加入队列
func QueuePush(name *C.char, val uintptr, vallen int) {
	data := CToBytes(val, vallen)
	str := C.GoString(name)
	QueueLock.Lock()
	Object := Queue[str]
	QueueLock.Unlock()
	if Object == nil {
		return
	}
	Object.Push(data)
}

//export QueuePull
//队列弹出
func QueuePull(name *C.char, rlen *int) uintptr {
	str := C.GoString(name)
	QueueLock.Lock()
	Object := Queue[str]
	QueueLock.Unlock()
	if Object == nil {
		return 0
	}
	bx := Object.Pull()
	if len(bx) < 1 {
		return 0
	}
	*rlen = len(bx)
	return uintptr(unsafe.Pointer(&bx[0]))
}

func (q *ArrayQueue) IsEmpty() bool {
	q.Lock.Lock()
	defer q.Lock.Unlock()
	return q.Size == 0
}
func (q *ArrayQueue) Empty() {
	q.Lock.Lock()
	defer q.Lock.Unlock()
	q.Size = 0
	q.Array = make([][]byte, 0)
}
func (q *ArrayQueue) Length() int {
	q.Lock.Lock()
	defer q.Lock.Unlock()
	return q.Size
}
func (q *ArrayQueue) Push(v []byte) {
	q.Lock.Lock()
	defer q.Lock.Unlock()
	q.Array = append(q.Array, v)
	q.Size++
}
func (q *ArrayQueue) Pull() []byte {
	q.Lock.Lock()
	defer q.Lock.Unlock()
	if q.Size == 0 {
		return []byte{}
	}
	v := q.Array[0]
	q.Array = q.Array[1:]
	q.Size--
	return v
}
