/*
Call Signal Processor
*/

package icssessionmanager

import (
	"time"
	"strings"

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

func (s *IcsSession) Processing(sip *parser.SIP) *icserror.IcsError {
	if sip == nil {
		return icserror.ICSERRInvalidParam
	}

	l := icslog.GetIcsLog()
	conf := icsconf.GetIcsConfig()

	switch sip.Method {
	case parser.ICS_SIP_METHOD_REGISTER:
		return s.ProcRegister(sip)

	case parser.ICS_SIP_METHOD_INVITE:
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "INVITE")
		//time.Sleep(3000 * time.Millisecond)
		//return nil
		return s.PassInvite(sip)
		// return s.ProcInvite(sip)

	case parser.ICS_SIP_METHOD_PUBLISH:
	case parser.ICS_SIP_METHOD_OPTIONS:
	case parser.ICS_SIP_METHOD_INFO:
	case parser.ICS_SIP_METHOD_UPDATE:
	case parser.ICS_SIP_METHOD_REFER:
		s.RequestBYE(s.InviteSIP)
	case parser.ICS_SIP_METHOD_SUBSCRIBE:
	case parser.ICS_SIP_METHOD_MESSAGE:
	case parser.ICS_SIP_METHOD_NOTIFY:
		s.ProcReferNotify200ok(sip)
	case parser.ICS_SIP_METHOD_PRACK:
	case parser.ICS_SIP_METHOD_ACK:
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "ACK - %+v", sip)
		// s.InviteSIP = sip

		if s.GetAgentStatus() == STATUS_AGENT_CALLING {
			s.SetAgentStatus(STATUS_AGENT_BUSY)

			//s.RTPSenderCallBackTimer.Start()
			//l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Started [%s]RTP callback timer", conf.AgentConfig[s.ID].Name)
		} else if s.GetAgentStatus() == STATUS_AGENT_ERROR {
			s.RequestBYE(s.InviteSIP)
			s.SetAgentStatus(STATUS_AGENT_READY)
		}
		/*else {
			l.Print(icslog.LOG_LEVEL_INFO, s.ID, "ACK")
		}
		*/
	case parser.ICS_SIP_METHOD_BYE:
		l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "BYE")
		status := s.GetAgentStatus()
		if status == STATUS_AGENT_BUSY {
			s.RTPSenderCallBackTimer.Stop()
			l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Stoped [%s] RTP callback timer", conf.AgentConfig[s.ID].Name)
		}
		err := s.ProcBye(sip)
		if err != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not process BYE method - %s", err.GetMessage())
		}
		s.RemoveSession()
		//////////////////////////////////
		//////// for simul //////////////
		//////////////////////////////////
		// send 83 to reg200
		l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Start Sim!!!")
		time.Sleep(time.Second)
		s.SendRequestInvite()
		//////////////////////////////////
		//////////////////////////////////
		//////////////////////////////////
	case parser.ICS_SIP_METHOD_CANCEL:
		s.RTPSenderCallBackTimer.Stop()
		l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Stoped [%s] RTP callback timer", conf.AgentConfig[s.ID].Name)
		err := s.ProcCancel(sip)
		if err != nil {
			l.Printf(icslog.LOG_LEVEL_ERROR, s.ID, "Could not process CANCEL method - %s", err.GetMessage())
		}
	case parser.ICS_SIP_METHOD_SIP20: //recved response proc
		switch GetJobType(sip) {
		case ICS_SIP_JOB_TYPE_REGISTER:
			//check status code
			code := sip.Source
			if strings.Compare(code, "200") == 0 {
				s.SetRegisterStatus(STATUS_REGISTER_REGISTERED)
				s.SetAgentStatus(STATUS_AGENT_READY)

				//s.INVITECallBackTimer.Start()
				//defer s.INVITECallBackTimer.Stop()

				l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Agent [%s] registered [%s]", s.AgentName, s.callID)

				s.RemoveSession()
			}
		case ICS_SIP_JOB_TYPE_INVITE:
			s.InviteSIP = sip
			//l.Printf(icslog.LOG_LEVEL_DEBUG2, s.ID, "sip20 invite - %s", sip.Source)

			code := sip.Source
			switch code {
			case "100":
			case "180":
			case "183":
			case "200":
				//response ACK
				s.ProcACKInvite(sip)
			default:
				//response ACK
				s.ProcACKInvite(sip)
			}
		case ICS_SIP_JOB_TYPE_PUBLISH:
		case ICS_SIP_JOB_TYPE_OPTIONS:
			// s.RequestInvite("01024342788")
		case ICS_SIP_JOB_TYPE_INFO:
		case ICS_SIP_JOB_TYPE_UPDATE:
		case ICS_SIP_JOB_TYPE_REFER:
		case ICS_SIP_JOB_TYPE_SUBSCRIBE:
		case ICS_SIP_JOB_TYPE_MESSAGE:
		case ICS_SIP_JOB_TYPE_NOTIFY:
		case ICS_SIP_JOB_TYPE_PRACK:
		case ICS_SIP_JOB_TYPE_ACK:
		case ICS_SIP_JOB_TYPE_BYE:
			if s.GetAgentStatus() == STATUS_AGENT_BUSY || s.GetAgentStatus() == STATUS_AGENT_BYEING {
				s.ProcSIP20Bye(sip)
			}
		case ICS_SIP_JOB_TYPE_CANCEL:
			/*
				//check status code
				code := sip.Source
				if strings.Compare(code, "200") == 0 {
					s.SetAgentStatus(STATUS_AGENT_READY)
					l.Printf(icslog.LOG_LEVEL_INFO, s.ID, "Agent [%s] CANCELed", s.AgentName)
				}
			*/
		default:
		}
	case parser.ICS_SIP_METHOD_NOT_FOUND:
	default:
	}

	return nil
}
