//for SELVAS streaming TTS
package tts

/*
#cgo LDFLAGS: /home/leejj9612/dev/voiceagent/extlib/selvastts/lib/Linux/C/x64/libpttsnet_m.a
#cgo CFLAGS: -I /home/leejj9612/dev/voiceagent/extlib/selvastts/include
#include <stdio.h>
#include <stdlib.h>
#include <pttsnet.h>
#include <pserrno.h>

*/
import "C"
import (
	"unsafe"

	"gitlab.com/cinnamon/voiceagent/icserror"
)

const (
	DEFAULT_STTS_PITCH    = -1
	DEFAULT_STTS_SPEED    = -1
	DEFAULT_STTS_VOLUME   = -1
	DEFAULT_STTS_LANGUAGE = 0
	DEFAULT_STTS_SPEAKER  = 8
	FRAMESIZE             = 32000
	CONNECTION_TIMEOUT    = 3
	READWRITE_TIMEOUT     = 5
)

//for selvas tts
type STTS struct {
	handle int
	ch     int
	text   string
	pitch  int
	vol    int
	speed  int
}

func NewSTTS(IP, port, text string) (*STTS, *icserror.IcsError) {
	if len(IP) <= 0 || len(port) <= 0 {
		return nil, icserror.ICSERRInvalidParam
	}

	stts := STTS{handle: -1, text: text, pitch: DEFAULT_STTS_PITCH, vol: DEFAULT_STTS_VOLUME, speed: DEFAULT_STTS_SPEED}

	csIP := C.CString(IP)
	csPort := C.CString(port)

	rc := C.PTTSNET_INIT(DEFAULT_STTS_LANGUAGE, DEFAULT_STTS_SPEAKER, csIP, csPort, CONNECTION_TIMEOUT, READWRITE_TIMEOUT)
	if int(rc) < 0 {
		C.free(unsafe.Pointer(csIP))
		C.free(unsafe.Pointer(csPort))
		return nil, icserror.ICSERRTTSFailInit
	}
	stts.handle = int(rc)
	//fmt.Println("Inited STTS :", rc, stts.handle)

	csText := C.CString(text)
	//fmt.Println("open", time.Now())
	chrc := C.PTTSNET_OPEN(C.int(stts.handle), csText, C.PTTSNET_FMT8K_16BIT_PCM, DEFAULT_STTS_PITCH, DEFAULT_STTS_SPEED, DEFAULT_STTS_VOLUME, 0, C.PTTSNET_CONTENT_PLAIN, C.PTTSNET_CHARSET_UTF8)
	if int(chrc) < 0 {
		//fmt.Println("failed open tts")
		C.free(unsafe.Pointer(csIP))
		C.free(unsafe.Pointer(csPort))
		C.free(unsafe.Pointer(csText))
		return nil, icserror.ICSERRTTSFailInit
	}
	stts.ch = int(chrc)
	//fmt.Println("TTS opened :", stts.ch)

	C.free(unsafe.Pointer(csIP))
	C.free(unsafe.Pointer(csPort))
	C.free(unsafe.Pointer(csText))

	return &stts, nil
}

func (s *STTS) Close() *icserror.IcsError {
	if s.handle < 0 || s.ch < 0 {
		return icserror.ICSERRTTSNotInit
	}

	rc := C.PTTSNET_CLOSE(C.int(s.ch), nil)
	if int(rc) != 0 {
		return icserror.ICSERRTTSFail
	}

	//fmt.Println(rc)
	//fmt.Println("close", time.Now())

	rc = C.PTTSNET_EXIT(C.int(s.handle))
	if int(rc) != 0 {
		return icserror.ICSERRTTSFail
	}
	//fmt.Println(rc)

	s.text = ""
	s.handle = -1
	s.ch = -1

	return nil
}

func (s *STTS) Read() ([]byte, int, *icserror.IcsError) {
	if s.handle < 0 || s.ch < 0 {
		return nil, -1, icserror.ICSERRTTSNotInit
	}

	frameBuf := make([]byte, FRAMESIZE)

	nSize := C.PTTSNET_READ(C.int(s.ch), (*C.char)(unsafe.Pointer(&frameBuf[0])), FRAMESIZE)
	if int(nSize) < 0 {
		//fmt.Println("Failed to read TTS")
		return nil, -1, icserror.ICSERRTTSFail
	} else if int(nSize) == 0 {
		return nil, -1, icserror.ICSERRTTSOK
	}
	//fmt.Println(nSize, time.Now())

	return frameBuf, int(nSize), icserror.ICSERRTTSContinue
}
