package mqttClient

import (
	"PPOSUtils/utils"
	"errors"
	"fmt"
	"time"
)

func NewDeviceApp(deviceType, MqttAddress, userName, password string) *DeviceApp {
	_deviceApp := &DeviceApp{
		deviceType:   "device_" + deviceType,
		mqttHost:     MqttAddress,
		mqttUsername: userName,
		mqttPassword: password,
	}
	return _deviceApp.init()
}

type DeviceApp struct {
	mqttPubID  string
	deviceType string
	//
	mqttHost     string
	mqttUsername string
	mqttPassword string
	//
	subClient *MqttClient
	pubClient *MqttClient
	//
	cmdHanderMap map[string]func(deviceID string, mp utils.Mp) error
}

func (that *DeviceApp) init() *DeviceApp {
	if that.subClient == nil {
		that.subClient = NewMqttClient(that.mqttHost, that.mqttUsername, that.mqttPassword)
	}
	if that.pubClient == nil {
		that.pubClient = NewMqttClient(that.mqttHost, that.mqttUsername, that.mqttPassword)
	}
	return that
}

func (that *DeviceApp) SetCmdHander(cmdType string, hander func(deviceID string, mp utils.Mp) error) {
	if that.cmdHanderMap == nil {
		that.cmdHanderMap = map[string]func(deviceID string, mp utils.Mp) error{}
	}
	that.cmdHanderMap[cmdType] = hander
}

func (that *DeviceApp) Start() error {
	//mqtt init
	if _err := that.subClient.Conn(fmt.Sprintf("%s-%d", that.deviceType+"-sub", time.Now().Unix())); _err != nil {
		return errors.New("mqtt sub conn fail:" + _err.Error())
	}
	that.mqttPubID = fmt.Sprintf("%s-%d", that.deviceType+"-pub", time.Now().UnixNano())
	if _err := that.pubClient.Conn(that.mqttPubID); _err != nil {
		return errors.New("mqtt pub conn fail:" + _err.Error())
	}
	return nil
}

func (that *DeviceApp) NewCmdRequest(deviceCode string) *CmdRequest {
	return &CmdRequest{
		deviceCode:   deviceCode,
		mqttPubID:    that.mqttPubID,
		mqttHost:     that.mqttHost,
		mqttUsername: that.mqttUsername,
		mqttPassword: that.mqttPassword,
		subClient:    that.subClient,
		pubClient:    that.pubClient,
		cmdHanderMap: that.cmdHanderMap,
	}
}

func (that *DeviceApp) Pub(deviceCode string, mp utils.Mp) error {
	_request := that.NewCmdRequest(deviceCode)
	return _request.Pub(mp)
}

func (that *DeviceApp) Sub(topic string) {
	_handler := NewMqttSubMessage(func(deviceID, topic, msgID string, data utils.Mp) {
		_request := that.NewCmdRequest(deviceID)
		if _err := _request.cmd(data); _err != nil {
		}
	})
	that.subClient.SubMsg(topic, _handler)
}

func (that *DeviceApp) UnSub(topic string) {
	that.subClient.UnSubMsg(topic)
}
