package controller

/*
#include <uvdbus/smart_sound.h>
*/
import "C"
import (
	"encoding/json"
	"errors"
	. "netease_control_center/globals"
	"netease_control_center/interfaces"
	"netease_control_center/interfaces/log"
	"sync"
)

var (
	CurYunxinStatus YunxinStatus = YunxinStatus{IsLogin: 0}
	yunxinlock                   = new(sync.Mutex)
	yunxinCond                   = sync.NewCond(yunxinlock)
	yunxinchan                   = make(chan *[]byte, 100)

	Err_Yunxin_Chan_Full = errors.New("云信缓存区已满")
)

func YunXinSendMsgRoutine() {
	for {
		log.Println(log.DebugLog, "Send yunxin msg routine start!")
		yunxinCond.L.Lock()
		for CurYunxinStatus.IsLogin == 0 {
			RequestYunxinStatus()
			yunxinCond.Wait()
		}
		yunxinCond.L.Unlock()
		log.Println(log.DebugLog, "Begin to send msg!")
		for msg := range yunxinchan {
			SendYunxinNoGuarantee(*msg)
		}

		log.Println(log.DebugLog, "Send yunxin msg finish, safely!")
	}
}

func DecodeYunxinStatus(data []byte) {
	var tmp YunxinStatus
	if err := json.Unmarshal(data, &tmp); err == nil {
		CurYunxinStatus = tmp
		if CurYunxinStatus.IsLogin == 1 {
			yunxinCond.Broadcast()
			log.Println(log.DebugLog, "Trigger yunxin msg send!")
		}
	}
}

func SendYunxinNoGuarantee(msg []byte) {
	interfaces.SendCommand(MODULE_CONTROLLER, MODULE_VOICEENGINE, uint32(C.CMD_YUNXIN_SENDMSG), &msg)
	//log.Println(log.DebugLog, "Send to yunxin: ", string(msg))
}

func SendYunxinGuarantee(msg []byte) error {
	select {
	case yunxinchan <- &msg:
		return nil
	default:
		return Err_Yunxin_Chan_Full
	}
}

func DbusYunxinStatus(data []byte) {
	var tmp YunxinStatus
	if err := json.Unmarshal(data, &tmp); err == nil {
		yunxinlock.Lock()
		CurYunxinStatus = tmp
		yunxinCond.Signal()
		yunxinlock.Unlock()
	}
}

func RequestYunxinStatus() {
	interfaces.JustSendBusCmd(MODULE_CONTROLLER, MODULE_VOICEENGINE, uint32(C.CMD_YUNXIN_STATUS))
}

func SendCmdByYunxin(cmd Cmd, detail interface{}, safe bool, replyid string) {
	var tmp AppParamBase
	tmp.CmdId = cmd
	tmp.ReplyId = replyid

	if data, err := json.Marshal(detail); err == nil {
		tmp.Detail = string(data)
	} else {
		log.Println(log.ErrorLog, "json code error:", err)
	}

	if data, err := json.Marshal(tmp); err == nil {
		if safe == false {
			SendYunxinNoGuarantee(data)
		} else {
			SendYunxinGuarantee(data)
		}
		//log.Printf(log.WarningLog, "SendCmdByYunxin:%+v\n", string(data))
	} else {
		log.Println(log.ErrorLog, "json code error:", err)
	}
}

type DeviceEventType int

const (
	DeviceEventType_Alarm           DeviceEventType = 1
	DeviceEventType_FirstWifiParing DeviceEventType = 2
	DeviceEventType_IotWifiParing   DeviceEventType = 3
)

type DeviceEventAction int

const (
	DeviceEventAction_Start DeviceEventAction = 1
	DeviceEventAction_End                     = 2
)

type DeviceEventStruct struct {
	EventType DeviceEventType   `json:"eventType"`
	Action    DeviceEventAction `json:"action"`
	Arg       string            `json:"arg"`
}

func SendEventByYunxin(event DeviceEventType, action DeviceEventAction, arg interface{}) {
	SendEventnByYunxinWithRid(event, action, "", true, arg)
}

func SendEventnByYunxinWithRid(event DeviceEventType, action DeviceEventAction, replyid string, safe bool, arg interface{}) {
	var tmp DeviceEventStruct
	if arg != nil {
		if data, err := json.Marshal(arg); err == nil {
			tmp.Arg = string(data)
		}
	}

	tmp.EventType = event
	tmp.Action = action

	SendCmdByYunxin(APP_CMD_DEVICE_EVENT, tmp, safe, "")
}
