package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"net"
	"os/exec"
	"strings"
	"syscall"
	"time"
	"unsafe"

	MQTT "github.com/eclipse/paho.mqtt.golang"
)

var MqttXyz = MqttClient{}

// 连接服务器地址
var Host = "192.168.0.254"

var username string

// 接收服务器消息
var SubTopic = "home/system/pc"

// 定时向服务器发送 空字符 判断有返回 来确定是否连接
var PubTopic = "home/system/pctosystem"

func init() {
	ip, errip := getIp()
	if errip == nil {
		last := strings.LastIndex(ip, ".")
		Host = ip[0:last] + ".254"
	}
	username = GetMac()
}
func main() {
	ConnetXyz(username)
	for {
		time.Sleep(time.Minute * 5) //5分钟
		bl := MqttXyz.PublishXyz()
		if !bl {
			ConnetXyz(username)
		}

	}
}
func ConnetXyz(username string) {
	MqttXyz.MqttClientInit(Host, username, "abcdefg", username).SubscribeXyz(SubTopic)
}

type WindowsAlert struct {
}

func (class *WindowsAlert) StrPtr(s string) uintptr {
	return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
}
func (class *WindowsAlert) ShowMessage(title, text string) {
	user32dll, _ := syscall.LoadLibrary("user32.dll")
	user32 := syscall.NewLazyDLL("user32.dll")
	MessageBoxW := user32.NewProc("MessageBoxW")
	defer syscall.FreeLibrary(user32dll)
	MessageBoxW.Call(uintptr(0), class.StrPtr(text), class.StrPtr(title), uintptr(0))
	time.Sleep(time.Second * 3)
}

type MqttClient struct {
	Client MQTT.Client
}

func (class *MqttClient) MqttClientInit(host, username, passwd, clientId string) *MqttClient {
	opts := MQTT.NewClientOptions().AddBroker("tcp://" + host + ":1883")
	opts.SetUsername(username)
	opts.SetPassword(passwd)
	opts.SetClientID(clientId)
	class.Client = MQTT.NewClient(opts)
	return class
}

// 系统MQTT接收消息,邮件提示站长
func (class *MqttClient) SubscribeXyz(topic string) {
	//连接并等待连接成功
	if token := class.Client.Connect(); token.Wait() && token.Error() != nil {
		fmt.Println("conn")
	}

	class.Client.Subscribe(topic, byte(2), func(c MQTT.Client, m MQTT.Message) {
		mm := make(map[string]string)
		err := json.Unmarshal(m.Payload(), &mm)
		if err == nil {

			if mm["username"] == username {
				switch mm["msg"] {
				case "关机":
					//fmt.Println("关机")
					arg := []string{"-s", "-t", "0"}
					cmd := exec.Command("shutdown", arg...)
					cmd.CombinedOutput()
				case "重启":
					arg := []string{"-r", "-t", "0"}
					cmd := exec.Command("shutdown", arg...)
					cmd.CombinedOutput()
				default:
					x := WindowsAlert{}
					x.ShowMessage("系统消息", mm["msg"])
				}
			}
		}

	})
}
func (class *MqttClient) PublishXyz() bool {
	token := class.Client.Publish(PubTopic, byte(1), false, username)
	if token.Error() != nil {
		class.Client.Disconnect(1)
		//fmt.Println("发布失败")
		return false
	}
	if !token.WaitTimeout(3 * time.Second) {
		//fmt.Println("发布失败Timeout")
		class.Client.Disconnect(1)
		return false
	}
	//fmt.Println("发布ok")
	return true
}
func GetMac() string {
	netInterfaces, err := net.Interfaces()
	if err != nil {
		return ""
	}
	for _, i2 := range netInterfaces {
		//fmt.Println(i2.Name)
		mac := i2.HardwareAddr
		//fmt.Println(mac)
		return mac.String()
	}
	return ""
}
func getIp() (string, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		fmt.Println(err)
		return "", errors.New(err.Error())
	}

	for _, address := range addrs {
		// 检查IP地址，其他类型的地址(如link-local或者loopback)忽略
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
			return ipnet.IP.String(), nil
		}
	}
	return "", errors.New("失败")
}
