package recorddata

import (
	"encoding/binary"
	"fmt"

	"gitlab.com/ics_cinnamon/voicegateway/icserror"
	"gitlab.com/ics_cinnamon/voicegateway/icslog"
	"gitlab.com/ics_cinnamon/voicegateway/icspacketparser"
)

type VoiceData struct {
	stream []byte
}

type VoiceDataHDR struct {
	ServerID   int
	CreateTime int64
	Station    int
	Seq        int
	Type       byte
	Codec      string
	Payload    []byte
}

const (
	VOICE_DATA_LEN = 340

	vcSERVERID_POS   = 0
	vcSERVERID_LEN   = 2
	vcCREATETIME_POS = vcSERVERID_POS + 2
	vcCREATETIME_LEN = vcCREATETIME_POS + 8
	vcSTATION_POS    = vcCREATETIME_POS + 8
	vcSTATION_LEN    = vcSTATION_POS + 4
	vcSEQUENCE_POS   = vcSTATION_POS + 4
	vcSEQUENCE_LEN   = vcSEQUENCE_POS + 4
	vcTYPE_POS       = vcSEQUENCE_POS + 4
	vcTYPE_LEN       = vcTYPE_POS + 1
	vcCODEC_POS      = vcTYPE_POS + 1
	vcCODEC_LEN      = vcCODEC_POS + 1
	vcPAYLOAD_POS    = vcCODEC_POS + 1
	vcPAYLOAD_LEN    = vcPAYLOAD_POS + 320
)

func NewVoiceData() *VoiceData {
	v := &VoiceData{
		stream: make([]byte, VOICE_DATA_LEN),
	}

	return v
}

func NewVoiceDataHDR(voicedata []byte) *VoiceDataHDR {
	hdr := VoiceDataHDR{}
	hdr.parse(voicedata)

	return &hdr
}

func (hdr *VoiceDataHDR) parse(data []byte) {
	defer func() {
		if err := recover(); err != nil {
			l := icslog.GetIcsLog()
			l.Print(icslog.LOG_LEVEL_WARN, -1, icserror.ICSERRRECORDDATAParsing.GetMessage())
		}
	}()

	hdr.ServerID = int(binary.LittleEndian.Uint16(data[vcSEQUENCE_POS:vcSEQUENCE_LEN]))
	hdr.CreateTime = int64(binary.LittleEndian.Uint64(data[vcCREATETIME_POS:vcCREATETIME_LEN]))
	hdr.Station = int(binary.LittleEndian.Uint32(data[vcSTATION_POS:vcSTATION_LEN]))
	hdr.Seq = int(binary.LittleEndian.Uint32(data[vcSEQUENCE_POS:vcSEQUENCE_LEN]))
	hdr.Type = data[vcTYPE_POS:vcTYPE_LEN][0]
	hdr.Codec = fmt.Sprintf("%d", data[vcCODEC_POS:vcCODEC_LEN])
	hdr.Payload = data[vcPAYLOAD_POS:vcPAYLOAD_LEN]
}

func (v *VoiceData) SetData(serverID int, station string, sequence int32, timestamp int64, calltype string, codec icspacketparser.PayloadType, payload []byte) {
	v.setServerID(serverID)
	v.setCreateTime(timestamp)
	v.setStation(station)
	v.setSequence(sequence)
	v.setType(calltype)
	v.setCodec2(codec)
	//v.setCodec(codec)
	v.setPayload(payload)
}

func (v VoiceData) GetData() []byte {
	return v.stream
}

func (v *VoiceData) setServerID(serverID int) {
	id := fmt.Sprintf("%d", serverID)
	tmp := []byte(id)
	copy(v.stream[vcSERVERID_POS:vcSERVERID_LEN], tmp)

	//l := icslog.GetIcsLog()
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setServerID> %d-%v", len(v.stream[vcSERVERID_POS:vcSERVERID_LEN]), v)
}

func (v *VoiceData) setCreateTime(createtime int64) {
	tmp := make([]byte, 8)
	binary.LittleEndian.PutUint64(tmp, uint64(createtime))
	copy(v.stream[vcCREATETIME_POS:vcCREATETIME_LEN], tmp)

	//l := icslog.GetIcsLog()
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setCreateTime> %d-%v", len(v.stream[vcCREATETIME_POS:vcCREATETIME_LEN]), v)
}

func (v *VoiceData) setStation(station string) {
	//tmp := make([]byte, 4)
	//binary.LittleEndian.PutUint32(tmp, uint32(station))
	copy(v.stream[vcSTATION_POS:vcSTATION_LEN], []byte(station))

	//l := icslog.GetIcsLog()
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setStation> %d-%v", len(v.stream[vcSTATION_POS:vcSTATION_LEN]), v)
}

func (v *VoiceData) setSequence(sequence int32) {
	tmp := make([]byte, 4)
	binary.LittleEndian.PutUint32(tmp, uint32(sequence))
	copy(v.stream[vcSEQUENCE_POS:vcSEQUENCE_LEN], tmp)

	//l := icslog.GetIcsLog()
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setSequence> %d-%v", len(v.stream[vcSEQUENCE_POS:vcSEQUENCE_LEN]), v)
}

func (v *VoiceData) setType(calltype string) {
	tmp := make([]byte, 4)
	if calltype == "0" {
		binary.LittleEndian.PutUint32(tmp, uint32(0))
	} else {
		binary.LittleEndian.PutUint32(tmp, uint32(1))
	}

	copy(v.stream[vcTYPE_POS:vcTYPE_LEN], tmp)

	//l := icslog.GetIcsLog()
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setType> %d-%v", len(v.stream[vcTYPE_POS:vcTYPE_LEN]), v)
}

func (v *VoiceData) setCodec(codec string) {
	tmp := make([]byte, 4)
	if codec == "0" {
		binary.LittleEndian.PutUint32(tmp, uint32(0))
	} else if codec == "8" {
		binary.LittleEndian.PutUint32(tmp, uint32(8))
	} else if codec == "18" {
		binary.LittleEndian.PutUint32(tmp, uint32(18))
	}
	copy(v.stream[vcCODEC_POS:vcCODEC_LEN], tmp)

	//l := icslog.GetIcsLog()
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setCodec> %d-%v", len(v.stream[vcCODEC_POS:vcCODEC_LEN]), v)
}

func (v *VoiceData) setCodec2(codec icspacketparser.PayloadType) {
	tmp := make([]byte, 4)
	if codec == 0 {
		binary.LittleEndian.PutUint32(tmp, uint32(0))
	} else if codec == 8 {
		binary.LittleEndian.PutUint32(tmp, uint32(8))
	} else if codec == 18 {
		binary.LittleEndian.PutUint32(tmp, uint32(18))
	}
	copy(v.stream[vcCODEC_POS:vcCODEC_LEN], tmp)

	//l := icslog.GetIcsLog()
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setCodec> %d-%v", len(v.stream[vcCODEC_POS:vcCODEC_LEN]), v)
}

func (v *VoiceData) setPayload(payload []byte) {
	copy(v.stream[vcPAYLOAD_POS:vcPAYLOAD_LEN], payload)

	//l := icslog.GetIcsLog()
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, -1, "setPayload> %d-%v", len(v.stream[vcPAYLOAD_POS:vcPAYLOAD_LEN]), v)
}

func (v VoiceData) GetServerID() []byte {
	return v.stream[vcSERVERID_POS:vcSERVERID_LEN]
}

func (v VoiceData) GetCreateTime() []byte {
	return v.stream[vcCREATETIME_POS:vcCREATETIME_LEN]
}

func (v VoiceData) GetStation() []byte {
	return v.stream[vcSTATION_POS:vcSTATION_LEN]
}

func (v VoiceData) GetSequence() []byte {
	return v.stream[vcSEQUENCE_POS:vcSEQUENCE_LEN]
}

func (v VoiceData) GetType() []byte {
	return v.stream[vcTYPE_POS:vcTYPE_LEN]
}

func (v VoiceData) GetCodec() []byte {
	return v.stream[vcCODEC_POS:vcCODEC_LEN]
}

func (v VoiceData) GetPayload() []byte {
	return v.stream[vcPAYLOAD_POS:vcPAYLOAD_LEN]
}
