package main

import (
	"github.com/gogf/gf/encoding/gjson"
	"sparrow/pkg/deviceAlarm"
	"sparrow/pkg/deviceStatus"
	"sparrow/pkg/online"
	"sparrow/pkg/otaUpgrade"
	"sparrow/pkg/rpcs"
	"sparrow/pkg/scene"
	"sparrow/pkg/token"
)

type DeviceManager struct {
	onlineManager *online.Manager
	tokenHelper   *token.Helper
	otaManager    *otaUpgrade.OtaManager
	statusManager *deviceStatus.DevStatusManager
	alarmManager  *deviceAlarm.DevAlarmManager
	sceneManager  *scene.Manager
}

func NewDeviceManager(redishost string, port, db int) *DeviceManager {
	mgr := online.NewManager(redishost, port, db)
	helper := token.NewHelper(redishost, port, db)
	otaMgr := otaUpgrade.NewOtaManager(redishost, port, db)
	statusMgr := deviceStatus.NewDevStatusManager(redishost, port)
	alarmMgr := deviceAlarm.NewDevAlarmManager(redishost, port)
	sceneMgr := scene.NewSceneManager(redishost, port)
	return &DeviceManager{
		onlineManager: mgr,
		tokenHelper:   helper,
		otaManager:    otaMgr,
		statusManager: statusMgr,
		alarmManager:  alarmMgr,
		sceneManager:  sceneMgr,
	}
}

func (dm *DeviceManager) GenerateDeviceAccessToken(args rpcs.ArgsGenerateDeviceAccessToken, reply *rpcs.ReplyGenerateDeviceAccessToken) error {
	token, err := dm.tokenHelper.GenerateToken(args.Id)
	if err != nil {
		return err
	}

	reply.AccessToken = token
	return nil
}

func (dm *DeviceManager) ValidateDeviceAccessToken(args rpcs.ArgsValidateDeviceAccessToken, reply *rpcs.ReplyValidateDeviceAccessToken) error {
	return dm.tokenHelper.ValidateToken(args.Id, args.AccessToken)
}

func (dm *DeviceManager) GetOnline(args rpcs.ArgsGetOnline, reply *rpcs.ReplyGetOnline) error {
	return dm.onlineManager.GetOnline(args.Id, online.Status{
		ClientIP:          args.ClientIP,
		AccessRPCHost:     args.AccessRPCHost,
		HeartbeatInterval: args.HeartbeatInterval,
	})
}

func (dm *DeviceManager) GetOnlineV2(args rpcs.ArgsGetOnline, reply *rpcs.ReplyGetOnline) error {
	return dm.onlineManager.GetOnlineV2(args.Id, online.Status{
		ClientIP:          args.ClientIP,
		AccessRPCHost:     args.AccessRPCHost,
		HeartbeatInterval: args.HeartbeatInterval,
	})
}

func (dm *DeviceManager) HeartBeat(args rpcs.ArgsHeartBeat, reply *rpcs.ReplyHeartBeat) error {
	return dm.onlineManager.SetHeartbeat(args.Id)
}

func (dm *DeviceManager) GetOffline(args rpcs.ArgsGetOffline, reply *rpcs.ReplyGetOffline) error {
	return dm.onlineManager.GetOffline(args.Id)
}

func (dm *DeviceManager) GetDeviceOnlineStatus(args rpcs.ArgsGetDeviceOnlineStatus, reply *rpcs.ReplyGetDeviceOnlineStatus) error {
	status, err := dm.onlineManager.GetStatus(args.Id)
	if err != nil {
		return err
	}

	if status != nil {
		reply.ClientIP = status.ClientIP
		reply.AccessRPCHost = status.AccessRPCHost
		reply.HeartbeatInterval = status.HeartbeatInterval
	}

	return nil
}

func (dm *DeviceManager) SavaFile(args rpcs.ArgsOtaFile, reply *rpcs.ReplyGetOffline) error {
	err := dm.otaManager.SavaFile(args.FileId, args.FileData)
	if err != nil {
		return err
	}
	return nil
}

func (dm *DeviceManager) GetFile(args rpcs.ArgsOtaFile, reply *rpcs.ReplyOtaFile) error {
	file, err := dm.otaManager.GetFile(args.FileId)
	if err != nil {
		return err
	}
	if file != nil {
		reply.File = file.FileData
	}
	return nil
}

func (dm *DeviceManager) UpdateProgress(args rpcs.ArgsOtaProgress, reply *rpcs.ReplyGetOffline) error {
	err := dm.otaManager.UpdateProgress(args.DeviceId, args.Progress)
	if err != nil {
		return err
	}
	return nil
}

func (dm *DeviceManager) GetProgress(args rpcs.ArgsOtaProgress, reply *rpcs.ReplyOtaProgress) error {
	progress, err := dm.otaManager.GetProgress(args.DeviceId)
	if err != nil {
		return err
	}
	if progress != nil {
		reply.Progress = progress.Progress
	}
	return nil
}

func (dm *DeviceManager) GetDeviceStatus(args rpcs.ArgsGetStatus, reply *rpcs.ReplyStatus) error {
	status, err := dm.statusManager.GetDeviceStatus(args.Id, args.ProductId)
	if err != nil {
		return err
	}
	if status != "" {
		reply.Status = status
	}
	return nil
}

func (dm *DeviceManager) GetDeviceInfo(args rpcs.ArgsGetStatus, reply *rpcs.ReplayInfo) error {
	info, err := dm.statusManager.GetDeviceInfo(args.Id, args.ProductId)
	if err != nil {
		return err
	}
	if info != "" {
		reply.Info = info
	}
	return nil
}

func (dm *DeviceManager) GetDeviceEvent(args rpcs.ArgsGetStatus, reply *rpcs.ReplayEvent) error {
	event, err := dm.statusManager.GetDeviceEvent(args.Id, args.ProductId)
	if err != nil {
		return err
	}
	if event != "" {
		reply.Event = event
	}
	return nil
}

func (dm *DeviceManager) GetDeviceStatusByKey(args rpcs.ArgsGetStatus, reply *rpcs.ReplyStatus) error {
	status, err := dm.statusManager.GetDeviceStatusByKey(args.Key)
	if err != nil {
		return err
	}
	if status != "" {
		reply.Status = status
	}
	return nil
}

func (dm *DeviceManager) GetWeatherInfo(args rpcs.ArgsGetWeather, reply *rpcs.ReplayWeatherInfo) error {
	info, err := dm.statusManager.GetWeatherInfo(args.Location)
	if err != nil {
		return err
	}
	if info != "" {
		reply.Info = info
	}
	return nil
}

func (dm *DeviceManager) SetWeatherInfo(args rpcs.ArgsSetWeather, reply *rpcs.ReplyEmptyResult) error {
	return dm.statusManager.SetWeatherInfo(args.Location, args.Info)
}

func (dm *DeviceManager) SetAlarm(args rpcs.ArgsAlarmInfo, reply *rpcs.ArgsAlarmInfo) error {
	return dm.alarmManager.SetAlarm(&deviceAlarm.AlarmParams{
		DeviceCode:      args.DeviceCode,
		FirstReportTime: args.FirstReportTime,
		LastAlarmTime:   args.LastAlarmTime,
	})
}

func (dm *DeviceManager) GetAlarm(args rpcs.ArgsGetAlarm, reply *rpcs.ReplayAlarm) error {
	info, err := dm.alarmManager.GetAlarm(args.DeviceCode)
	if err != nil {
		return err
	}
	if info != nil {
		reply.AlarmParams = info
	}
	return nil
}

func (dm *DeviceManager) DelAlarm(args rpcs.ArgsGetAlarm, reply *rpcs.ReplayAlarm) error {
	return dm.alarmManager.DeleteAlarm(args.DeviceCode)
}

func (dm *DeviceManager) GetAllScenesPage(args rpcs.ArgsGetAllScene, reply *rpcs.ReplyScenes) error {
	result, err := dm.sceneManager.GetAllScenesPage(args.Code, args.Pi, args.Ps)
	if err != nil {
		return err
	}
	if len(result.Data) > 0 {
		reply.Total = result.Total
		reply.Result = result.Data
	}
	return nil
}

func (dm *DeviceManager) GetAllScenes(args rpcs.ArgsGetAllScene, reply *rpcs.ReplyScenes) error {
	result, err := dm.sceneManager.GetAllScenes(args.Code)
	if err != nil {
		return err
	}
	if len(result) > 0 {
		reply.Result = result
	}
	return nil
}

func (dm *DeviceManager) SaveScene(args rpcs.ArgsScene, reply *rpcs.ReplyScene) error {
	return dm.sceneManager.SaveScene(&scene.InfoScene{
		Id:            args.SceneId,
		Key:           args.Key,
		SceneId:       args.SceneId,
		ConditionDesc: args.ConditionDesc,
		ActionDesc:    args.ActionDesc,
		Name:          args.Name,
		Config:        args.Config,
		Status:        args.Status,
		Time:          args.Time,
		SceneType:     args.SceneType,
	})
}

func (dm *DeviceManager) UpdateSceneStatus(args rpcs.ArgsScene, reply *rpcs.ReplyScene) error {
	info, err := dm.sceneManager.GetScene(args.Key)
	if err != nil {
		return err
	}
	j := gjson.New(info)
	newScene := new(scene.InfoScene)
	_ = j.Struct(newScene)
	newScene.Status = args.Status
	return dm.sceneManager.SaveScene(newScene)
}
func (dm *DeviceManager) GetScene(args rpcs.ArgsScene, reply *rpcs.ReplyScene) error {
	info, err := dm.sceneManager.GetScene(args.Key)
	if err != nil {
		return err
	}
	if info != "" {
		reply.Config = info
	}
	return nil
}

func (dm *DeviceManager) DeleteScene(args rpcs.ArgsScene, reply *rpcs.ReplyScene) error {
	return dm.sceneManager.DeleteScene(args.Key)
}
