package icssessionmanager

import (
	"encoding/json"
	"strings"

	"gitlab.com/cinnamon/voiceagent/icsconf"
	"gitlab.com/cinnamon/voiceagent/icserror"
	"gitlab.com/cinnamon/voiceagent/icsevent"
	"gitlab.com/cinnamon/voiceagent/icshttpclient"
	"gitlab.com/cinnamon/voiceagent/icslog"
	"gitlab.com/cinnamon/voiceagent/icsnet"
	"gitlab.com/cinnamon/voiceagent/recorddata/responsecs"
	"gitlab.com/cinnamon/voiceagent/stt"
	"gitlab.com/cinnamon/voiceagent/tts"
)

/////////////////////////////////////////////
// bot scenario
func (s *IcsSession) DoScenario(request *icshttpclient.IcsHttpClient) {
	l := icslog.GetIcsLog()
	conf := s.AgentConfig

	resBody, err := icshttpclient.ClientDo(request)
	if err != nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "ClientDo error - %s", err.GetMessage())
		s.botStatus = nil
		return
	}
	//l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "%s {%+v}", request.URL, resBody)

	if strings.Contains(request.URL, conf.BotConfig.URL1) { //serviceinfo
		l.Print(icslog.LOG_LEVEL_DEBUG2, s.ID, "URL: service info")

		var svcInfoResp *icshttpclient.ServiceInfoResp
		err1 := json.Unmarshal(resBody, &svcInfoResp)
		if err1 != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "URL: service info - unmarshal error(%s)", err1)
			return
		}
	} else if strings.Contains(request.URL, conf.BotConfig.URL2) { //process
		l.Print(icslog.LOG_LEVEL_DEBUG2, s.ID, "URL: process")

		var processResp *icshttpclient.ProcessResp
		err1 := json.Unmarshal(resBody, &processResp)
		if err1 != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "URL: process - unmarshal error(%s)", err1)
			s.botStatus = nil
			//TODO: error!
			return
		}
		s.botStatus = processResp
		if len(s.botToken) == 0 {
			s.botToken = s.botStatus.Token
		}
	}

	l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "%+v", s.botStatus)
	s.botScenario()
}

func (s *IcsSession) botScenario() {
	if s.botStatus == nil {
		return
	}

	l := icslog.GetIcsLog()

	switch s.botStatus.Action {
	case "STT":
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "STT> TTS announce: %s", s.botStatus.AnnounceMents)
		s.TTSandSTT()

	case "DTMF":
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "DTMF> TTS announce: %s", s.botStatus.AnnounceMents)
		s.TTSandDTMF()

	case "TRANSFER":
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "TRANSFER> TTS announce: %s", s.botStatus.AnnounceMents)
		s.TTSandTransfer()

	case "END":
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "END> TTS announce: %s", s.botStatus.AnnounceMents)
		s.TTSandEnd()

	default:
	}
}

////////////////////////////////////////////////////
func (s *IcsSession) STTResultCB(sttResult *stt.STTResult) {
	l := icslog.GetIcsLog()

	botRequest := icshttpclient.NewPostProcess(s.url, s.botStatus.Action, sttResult.GetResult(), s.custid, "ICS_RCP", s.callId, s.sstation, s.botToken, "")
	////////////////////////////////////////////////
	//post event to the session
	h := icsevent.NewEventH()
	var evt *icsevent.Event
	var evtErr *icserror.IcsError
	if evt, evtErr = h.AllocEvent(botRequest); evtErr != nil {
		l.Print(icslog.LOG_LEVEL_ERROR, s.ID, "Response Error")
		s.SendVoiceGatewayByeSignal()
		return
	}
	l.Printf(icslog.LOG_LEVEL_INFO, -1, "Post BOT Request[%d] to Session[%03d]", evt.ID, s.ID)
	h.PostEvent(s.ID, evt)
}

func (s *IcsSession) TTSandSTT() {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	agentname := s.AgentConfig.Name
	telno := s.botStatus.Data.TelNo

	//tts
	pcm, ttsErr := tts.TTS(s.botStatus.AnnounceMents, 8000)
	if ttsErr != nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "TTS Error[%s] - %s",
			s.botStatus.AnnounceMents, ttsErr.GetError())
		// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
		// break
		return
	} else {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "%s!!! TTS Result: [%s]%d bytes",
			agentname, s.botStatus.AnnounceMents, len(pcm))

		//send tts data to voice gateway
		r := responsecs.NewResponse(agentname, telno, responsecs.TTS_COMMAND, responsecs.RC_SUCCESS, len(pcm))
		addr := icsnet.NewNetAddrWithIPPort(conf.VGWCommandConfig.IP, conf.VGWCommandConfig.Port)
		t, wlen, werr := icsnet.SendCallSignal2(&addr, nil, r.GetData())
		//wlen, werr := s.TcpConn.Write(r.GetData())
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send TTS header - %s [%+v]",
				werr.GetError(), s.TcpConn)
			return
			// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
			// break
		}
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Sent TTS header : %d", wlen)

		s.TcpConn = t
		wlen, werr = s.TcpConn.Write(pcm)
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send TTS data - %s",
				werr.GetError())
			return
			// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
			// break
		}
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Sent TTS data : %d", wlen)

		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Barge-In: %s", s.botStatus.Data.BargeIn)
		switch s.botStatus.Data.BargeIn {
		case "Y":
			//s.StartSTT(wlen)
			s.isSTTStart = true
		case "N":
			s.StartSTT(wlen)
			//s.isSTTStart = false
		}
	}
}

func (s *IcsSession) DTMFCB() {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()
	dtmfEnd := conf.DtmfEndSignal.Signal

	dtmf := s.GetDtmf(dtmfEnd)
	if s.botStatus.Action == "DTMF" && dtmf != "" { // dtmf
		botRequest := icshttpclient.NewPostProcess(s.url, s.botStatus.Action, dtmf, s.custid, "ICS_RCP", s.callId, s.sstation, s.botToken, "")
		////////////////////////////////////////////////
		//post event to the session
		h := icsevent.NewEventH()
		var evt *icsevent.Event
		var evtErr *icserror.IcsError
		if evt, evtErr = h.AllocEvent(botRequest); evtErr != nil {
			l.Print(icslog.LOG_LEVEL_ERROR, s.ID, "Response Error")
			s.SendVoiceGatewayByeSignal()
			return
		}
		l.Printf(icslog.LOG_LEVEL_INFO, -1, "Post BOT Request[%d] to Session[%03d]", evt.ID, s.ID)
		h.PostEvent(s.ID, evt)
	}
}

func (s *IcsSession) TTSandDTMF() {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	agentname := s.AgentConfig.Name
	telno := s.botStatus.Data.TelNo

	s.ResetDtmf()

	//tts
	pcm, ttsErr := tts.TTS(s.botStatus.AnnounceMents, 8000)
	if ttsErr != nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "TTS Error[%s] - %s",
			s.botStatus.AnnounceMents, ttsErr.GetError())
		// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
		// break
		return
	} else {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "%s!!! TTS Result: [%s]%d bytes",
			agentname, s.botStatus.AnnounceMents, len(pcm))

		//send tts data to voice gateway
		r := responsecs.NewResponse(agentname, telno, responsecs.DTMF_COMMAND, responsecs.RC_SUCCESS, len(pcm))
		addr := icsnet.NewNetAddrWithIPPort(conf.VGWCommandConfig.IP, conf.VGWCommandConfig.Port)
		t, wlen, werr := icsnet.SendCallSignal2(&addr, nil, r.GetData())
		//wlen, werr := s.TcpConn.Write(r.GetData())
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send TTS header - %s [%+v]",
				werr.GetError(), s.TcpConn)
			return
			// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
			// break
		}
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Sent TTS header : %d", wlen)

		s.TcpConn = t
		wlen, werr = s.TcpConn.Write(pcm)
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send TTS data - %s",
				werr.GetError())
			return
			// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
			// break
		}
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Sent TTS data : %d", wlen)
	}
}

func (s *IcsSession) TTSandTransfer() {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	agentname := s.AgentConfig.Name
	telno := s.botStatus.Data.TelNo

	//tts
	pcm, ttsErr := tts.TTS(s.botStatus.AnnounceMents, 8000)
	if ttsErr != nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "TTS Error[%s] - %s",
			s.botStatus.AnnounceMents, ttsErr.GetError())
		// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
		// break
		return
	} else {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "%s!!! TTS Result: [%s]%d bytes",
			agentname, s.botStatus.AnnounceMents, len(pcm))

		//send tts data to voice gateway
		r := responsecs.NewResponse(agentname, telno, responsecs.REFER_COMMAND, responsecs.RC_SUCCESS, len(pcm))
		addr := icsnet.NewNetAddrWithIPPort(conf.VGWCommandConfig.IP, conf.VGWCommandConfig.Port)
		t, wlen, werr := icsnet.SendCallSignal2(&addr, nil, r.GetData())

		//wlen, werr := s.TcpConn.Write(r.GetData())
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send TTS header - %s [%+v]",
				werr.GetError(), s.TcpConn)
			return
			// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
			// break
		}
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Sent TTS header : %d", wlen)

		s.TcpConn = t
		wlen, werr = s.TcpConn.Write(pcm)
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send TTS data - %s",
				werr.GetError())
			return
			// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
			// break
		}
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Sent TTS data : %d", wlen)
	}
}

func (s *IcsSession) TTSandEnd() {
	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	agentname := s.AgentConfig.Name
	telno := s.botStatus.Data.TelNo

	//tts
	pcm, ttsErr := tts.TTS(s.botStatus.AnnounceMents, 8000)
	if ttsErr != nil {
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "TTS Error[%s] - %s",
			s.botStatus.AnnounceMents, ttsErr.GetError())
		// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
		// break
		return
	} else {
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "%s!!! TTS Result: [%s]%d bytes",
			agentname, s.botStatus.AnnounceMents, len(pcm))

		//send tts data to voice gateway
		r := responsecs.NewResponse(agentname, telno, responsecs.BYE_COMMAND, responsecs.RC_SUCCESS, len(pcm))
		addr := icsnet.NewNetAddrWithIPPort(conf.VGWCommandConfig.IP, conf.VGWCommandConfig.Port)
		t, wlen, werr := icsnet.SendCallSignal2(&addr, nil, r.GetData())
		//wlen, werr := s.TcpConn.Write(r.GetData())
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send TTS header - %s [%+v]",
				werr.GetError(), s.TcpConn)
			return
			// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
			// break
		}
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Sent TTS header : %d", wlen)

		s.TcpConn = t
		wlen, werr = s.TcpConn.Write(pcm)
		if werr != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Failed to send TTS data - %s",
				werr.GetError())
			return
			// s.SendVoiceGatewayBotByeSignal(url, custid, sstation)
			// break
		}
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "Sent TTS data : %d", wlen)
	}
}
