package gatewayServer

import (
	"encoding/xml"
	"fmt"
	"github.com/sirupsen/logrus"
	"lcfns/global"
	"lcfns/isapi"
	appModel "lcfns/model/app"
	"lcfns/service"
	appService "lcfns/service/app"
	is "lcfns/service/isapi"
	"net"
	"strings"
)

func ParseAndResponse(adu AppDataUnit, c net.Conn) {
	switch adu.CmdCode {
	case CmdCodeHeartbeatC2S:
		c2s4002(adu, c)
	case CmdCodeGetParamC2S:
		c2s4003(adu)
	case CmdCodeSetParameterC2S:
		c2s4004(adu)
	case CmdCodeRegisterC2S:
		c2s4001(adu, c)
	case CmdCodeServerC2S:
		c2s4000(adu, c)
	case CmdCodeUpdateC2S:
		//更新固件
	default:
		fmt.Println(adu.String())
	}
}

// 请求管理服务器响应
func c2s4000(adu AppDataUnit, c net.Conn) {
	a := AppDataUnit{
		CmdCode: CmdCodeServerS2C,
		SubCode: 0,
		DevId:   adu.DevId,
		Data:    ipAddress,
	}
	a.Debug()
	_, err := c.Write(Pack(a))
	if err != nil {
		logrus.Errorf("写入数据错误 %e\n", err)
	}
	logrus.Info(adu.DevId, "向登录服务器请求管理服务器")
}

// 注册登录响应
func c2s4001(adu AppDataUnit, c net.Conn) {
	a := AppDataUnit{
		CmdCode: CmdCodeRegisterS2C,
		SubCode: 0,
		DevId:   adu.DevId,
	}
	a.Data = "0"
	a.Debug()
	_, err := c.Write(Pack(a))
	if err != nil {
		logrus.Errorf("写入数据错误 %e\n", err)
	}
	ConnMap[adu.DevId] = c
	//1. 网关登录后检查是否已经注册到数据库,没有就要保存至数据库
	gs := service.ServiceGroupApp.AppServiceGroup.GatewayService
	gw, err := gs.CreateIfNotExist(adu.DevId)
	if err != nil {
		//if errors.Is(err, appService.ExistError) {
		if err == appService.ExistError {
			logrus.Infof("网关[%s]登录成功", adu.DevId)
		} else {
			//如果错误不是"已注册",退出
			logrus.WithField("网关注册失败", adu.DevId).Error(err)
			return
		}
	}
	//配置端口转发  配置不成功
	//err = s2c8004Set(a.DevId, SubCodePortTrans, sp)
	//if err != nil {
	//	logrus.Errorf("s2c8004Set %e\n", err)
	//}
	//2. 获取网关上摄像头和ip音柱的信息,保存至数据库
	var cs = service.ServiceGroupApp.AppServiceGroup.CameraService
	baseUrl := strings.Split(c.RemoteAddr().String(), ":")[0] + ":8848"
	resp, err := isapi.Com(baseUrl, isapi.GetDeviceInfo, nil)
	if err != nil {
		logrus.Error(err)
		return
	}
	var info isapi.DeviceInfo
	xml.Unmarshal(resp, &info)
	//创建camera记录并绑定gateway_id
	err = cs.CreateIfNotExist(info, gw.ID)
	if err != nil {
		logrus.WithField("摄像头注册失败", info.SerialNumber).Error(err)
	}
	//3.检查摄像头是否配置
	camera, err := cs.GetCameraByDeviceId(info.SerialNumber)
	if err != nil {
		logrus.Error(err)
		return
	}
	//已配置不执行下面
	if &camera != nil && camera.IsRegisted == 1 {
		return
	}
	//配置摄像头-事件监听服务器
	setServer(baseUrl)
	//配置摄像头-sip服务器
	setSIP(baseUrl, camera.ID, cs)
}

// 心跳响应
func c2s4002(adu AppDataUnit, c net.Conn) {
	//todo 心跳处理
	a := AppDataUnit{
		CmdCode: CmdCodeHeartbeatS2C,
		SubCode: 0,
		DevId:   adu.DevId,
	}
	a.Debug()
	_, err := c.Write(Pack(a))
	if err != nil {
		logrus.Errorf("写入数据错误 %e\n", err)
	}
	//logrus.Info("heartbeat :", adu.DevId)
	//todo 网关注册后,网关再接入摄像头如何注册摄像头--
}

// 查询参数响应
func c2s4003(adu AppDataUnit) {
	logrus.Infof("参数响应%s,devId:%s,CmdCode=%X,SubCode=%X\n", adu.Data, adu.DevId, adu.CmdCode, adu.SubCode)
}

// 设置参数响应
func c2s4004(adu AppDataUnit) {
	logrus.Infof("配置参数-响应码%s,devId:%s,CmdCode=%X,SubCode=%X\n", adu.Data, adu.DevId, adu.CmdCode, adu.SubCode)
}

func setServer(host string) uint {
	marshal, err := xml.Marshal(global.Config.HttpHostNotificationList)
	fmt.Println("host:", string(marshal))
	if err != nil {
		logrus.Errorf("事件主机配置文件解析错误: %e\n", err)
		return 0
	}
	bytes, err := isapi.Com(host, isapi.SetHosts, marshal)
	if err != nil {
		logrus.Error("配置监听主机错误", err)
	}
	var resp isapi.ResponseStatus
	err = xml.Unmarshal(bytes, &resp)
	if err != nil || (resp.StatusCode != 0 && resp.StatusCode != 1) {
		logrus.Errorf("配置监听服务器响应 err:%s,StatusCode:%d,StatusString:%s", err.Error(), resp.StatusCode, resp.StatusString)
		return 0
	}
	logrus.Info("配置监听主机响应", string(bytes))
	return 1
}

func setSIP(host string, cid uint, cs appService.CameraService) uint {
	//1. 准备数据
	var sipstr = `
<?xml version: "1.0" encoding="utf-8"?><SIPServerList xmlns="http://www.hikvision.com/ver20/XMLSchema" version="2.0">
<SIPServer>
<id>1</id>
<localPort>5060</localPort>
<streamID>1</streamID>
<Standard>
<registerStatus>false</registerStatus>
<enabled>false</enabled>
<registrar/>
<registrarPort>5060</registrarPort>
<proxy/>
<proxyPort>5060</proxyPort>
<displayName/>
<userName/>
<authID/>
<password/>
<expires>0</expires>
</Standard>
<GB28181>
<registerStatus>true</registerStatus>
<enabled>true</enabled>
<registrar>106.52.134.22</registrar>
<registrarPort>5060</registrarPort>
<serverId>34020000002000000001</serverId>
<serverDomain>3402000000</serverDomain>
<userName>34020000002000000%03d</userName>
<authID>34020000001320000%03d</authID>
<password>kk176@lc</password>
<expires>3600</expires>
<liveTime>1</liveTime>
<heartbeatTime>15</heartbeatTime>
<heartbeatCount>3</heartbeatCount>
<transportType>UDP</transportType>
<registerInterval>60</registerInterval>
<protocolVersion>GB/T28181-2016</protocolVersion>
<platformNo>1</platformNo>
<localPort>5060</localPort>
<unidirectionEnabled>false</unidirectionEnabled>
<voiceBroadcastEnabled>false</voiceBroadcastEnabled>
</GB28181>
</SIPServer>
</SIPServerList>`
	var sipInfo = `
<?xml version: "1.0" encoding="UTF-8"?>
<SIPInfo xmlns="http://www.hikvision.com/ver20/XMLSchema" version="2.0">
<videoID>34020000001320000001</videoID>
<AlarmInList>
</AlarmInList>
<VideoInputList>
<VideoInput>
<id>1</id>
<videoInputID>34020000001320000001</videoInputID>
</VideoInput>
</VideoInputList>
<AudioOutputList>
<AudioOutput>
<id>1</id>
<audioOutputID/>
</AudioOutput>
</AudioOutputList>
</SIPInfo>`
	//获取自增ID,以51为起始值
	id, err := is.GetSipUserID()
	if err != nil {
		logrus.Error("事务错误", err)
	}
	//2. 配置SIP
	s := fmt.Sprintf(sipstr, id, id)
	bytes, err := isapi.Com(host, isapi.SetSIP, []byte(s))
	if err != nil {
		logrus.Error("配置SIP错误", err)
		return 0
	}
	var resp isapi.ResponseStatus
	err = xml.Unmarshal(bytes, &resp)
	if err != nil {
		logrus.Errorf("配置SIP服务器err:%s", err.Error())
		return 0
	}
	//失败记录失败原因
	if resp.StatusCode != 0 && resp.StatusCode != 1 {
		logrus.Infof("配置SIP服务器响应 StatusCode:%d,StatusString:%s", resp.StatusCode, resp.StatusString)
		return 0
	}
	//3. 配置SIPInfo
	com, err := isapi.Com(host, isapi.SetSIPInfo, []byte(sipInfo))
	if err != nil {
		logrus.Error("配置SIPInfo错误", err)
		return 0
	}
	var resp1 isapi.ResponseStatus
	err = xml.Unmarshal(com, &resp1)
	if err != nil {
		logrus.Errorf("配置配置SIPInfo err:%s", err.Error())
		return 0
	}
	//记录失败原因
	if resp.StatusCode != 0 && resp.StatusCode != 1 {
		logrus.Infof("配置SIPInfo-响应 StatusCode:%d,StatusString:%s", resp.StatusCode, resp.StatusString)
		return 0
	}
	//成功保存数据库
	streamId := fmt.Sprintf("34020000002000000%03d@34020000001320000001", id)
	streamUrl := global.Config.Hikvision.StreamBaseUrl + streamId
	var camera = appModel.Camera{
		StreamId:   streamId,
		StreamUrl:  streamUrl,
		IsRegisted: 1,
	}
	camera.ID = cid
	err = cs.UpdateCamera(camera)
	if err != nil {
		logrus.Error(err)
	}
	return 1
}