package icsdtmf

import (
	"encoding/binary"
	"fmt"

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

type ICSDTMF struct {
	rfc2833 *RFC2833
}

func NewICSDTMF() *ICSDTMF {
	d := ICSDTMF{rfc2833: nil}

	return &d
}

func DTMF(dtmf *ICSDTMF, data interface{}, pcm []byte) (string, *icserror.IcsError) {
	switch v := (data).(type) {
	case icspacketparser.RTP:
		rtp := v
		switch rtp.GetPayloadType() { //in band
		case icspacketparser.DTMF101: //rtp 101
			//fmt.Println("101")
			rfc2833, d, derr := dtmfRFC2833(rtp)
			if rfc2833.Mark { //if rtp mark, reset old dtmf handle
				dtmf.rfc2833 = nil
				return "", icserror.ICSERRDTMFCont
			}
			if derr != icserror.ICSERRDTMFCont {
				if dtmf.rfc2833 == nil || !dtmf.rfc2833.isEqual(rfc2833) {
					dtmf.rfc2833 = rfc2833
					dtmf := fmt.Sprintf("%d", d)
					return dtmf, derr
				} else {
					return "", icserror.ICSERRDTMFCont
				}
			} else {
				return "", derr
			}
		case icspacketparser.PCMA:
			fallthrough
		case icspacketparser.G729:
			fallthrough
		case icspacketparser.PCMU: //bypass
			dtmfBypass(pcm)
		}
	case icspacketparser.SIP: //sip info. rfc2976
	}

	return "", icserror.ICSERRDTMFFail
}

func (d *ICSDTMF) Reset() {
	d.rfc2833 = nil
}

///////////////////////////////////////////////////////////////////////
//RFC 2833 - rtp event

type RFC2833 struct {
	Event    int
	End      bool
	Volume   int
	Duration int
	Mark     bool
}

func dtmfRFC2833(rtp icspacketparser.RTP) (*RFC2833, int, *icserror.IcsError) {
	r, err := parseRFC2833(rtp)
	if err == icserror.ICSERRDTMFFail {
		return nil, -1, err
	} else if err == icserror.ICSERRDTMFCont {
		return r, -1, err
	}
	event, err := r.GetDTMF()
	return r, event, err
}

func parseRFC2833(rtp icspacketparser.RTP) (*RFC2833, *icserror.IcsError) {
	r := RFC2833{}
	data := rtp.Payload

	r.End = data[1]&0x80 == 0x80
	if r.End {
		//fmt.Println("RTP Event End?", r.End, data[1], len(data))

		r.Event = int(data[0])
		//fmt.Println("DTMF :", r.Event)

		vol := data[1] << 2
		r.Volume = int(vol >> 2)
		//fmt.Println("vol", r.Volume, vol, data[1])

		dur := binary.BigEndian.Uint16(data[2:])
		r.Duration = int(dur)
		//fmt.Println("Dur", dur)
	} else {
		r.Mark = rtp.Mark
		return &r, icserror.ICSERRDTMFCont
	}

	r.Mark = rtp.Mark

	return &r, icserror.ICSERRDTMFOK
}

func (r RFC2833) GetDTMF() (int, *icserror.IcsError) {
	return r.Event, icserror.ICSERRDTMFOK
}

func (r RFC2833) isEqual(rfc2833 *RFC2833) bool {
	if r.Duration == rfc2833.Duration && r.End == rfc2833.End && r.Event == rfc2833.Event && r.Volume == rfc2833.Volume {
		return true
	}

	return false
}

///////////////////////////////////////////////////////////////////////
//bypass - audio
type ByPassDTMF struct {
	VoiceBuf []byte
}

func dtmfBypass(data []byte) (string, *icserror.IcsError) {

	return "", icserror.ICSERRDTMFFail
}
