package main

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

	"github.com/gorilla/websocket"
	//"github.com/spf13/viper"
)

/*
go build -o xxx.exe -ldflags "-s -w -H=windowsgui"
运行命令
shell:startup
把程序扔到里面
*/
var Tt = 3

func main() {
	go func() {
		//设置定时器为3小时
		timer := time.NewTimer(10800 * time.Second)
		fmt.Println("定时开始")
		for {
			<-timer.C
			//3小时后执行这条
			x := WindowsAlert{}
			if Tt > 3 {
				x.ShowMessage("弹窗提示", "您已经连续使用电脑 "+fmt.Sprintf("%d", Tt)+" 小时了,劳逸结合,准备自动关机")
				time.Sleep(time.Second * 10)
				fmt.Println("关闭主机")
				arg := []string{"-s", "-t", "0"}
				cmd := exec.Command("shutdown", arg...)
				cmd.CombinedOutput()
			} else {
				x.ShowMessage("弹窗提示", "您已经连续使用电脑 "+fmt.Sprintf("%d", Tt)+" 小时了,请关闭电脑休息一下,劳逸结合")
			}

			//重设定时时间
			timer.Reset(10800 * time.Second)
			Tt = Tt + 3
			fmt.Println("已经重设定时时间,正在回滚for 循环")
		}
	}()
	wss := "ws"
	//获取电脑主机名
	user, _ := os.Hostname()
	password := "efghijk"
	room := "pc"
	w := WebsocketClient{}
	w.NewInit("192.168.100.254", 80, "/service/wss", 10, wss, user, password, room).Start()

}

type WebsocketClient struct {
	conn        *websocket.Conn
	addr        *string
	path        string
	Userinfo    interface{}
	sendMsgChan chan string
	isAlive     bool //联网状态
	timeout     int
	wtype       string //连接 wss 还是ws
	user        string
	password    string
	room        string
	StartDate   string // 上线时间
	Ch          chan os.Signal
}

// 初始化 NewInit("www.360xyz.cn", 443, "/service/wss", 10, wss,user, password, room).Start()
func (class *WebsocketClient) NewInit(addrIp string, addrPort int, path string, timeout int, wtype, user, password, room string) *WebsocketClient {
	var conn *websocket.Conn
	temp := addrIp + ":" + fmt.Sprintf("%d", addrPort)
	class.conn = conn
	class.addr = &temp
	class.path = path
	class.sendMsgChan = make(chan string, 10)
	class.isAlive = false
	class.timeout = timeout
	class.wtype = wtype
	class.user = user
	class.password = password
	class.room = room
	class.Ch = make(chan os.Signal, 1)
	class.StartDate = time.Now().Format("2006-01-02 15:04")

	return class
}

// 链接服务端
func (class *WebsocketClient) dail(wtype, user, password, room string) {
	var err error
	u := url.URL{Scheme: wtype, Host: *class.addr, Path: class.path, ForceQuery: true, RawQuery: "user=" + user + "&password=" + password + "&room=" + room}
	fmt.Println("connecting to " + u.String())
	class.conn, _, err = websocket.DefaultDialer.Dial(u.String(), nil)
	if err != nil {
		fmt.Println(err)
		class.isAlive = false
		//os.Exit(1)
		return
	}
	class.isAlive = true
	fmt.Println("链接成功！！！")
	class.StartDate = time.Now().Format("2006-01-02 15:04")
	class.conn.WriteMessage(websocket.TextMessage, []byte("上线时间"+class.StartDate))

}

// 发送消息
func (class *WebsocketClient) sendMsgThread() {
	go func() {
		for {
			msg := <-class.sendMsgChan
			err := class.conn.WriteMessage(websocket.TextMessage, []byte(msg))
			if err != nil {
				fmt.Println("write:", err)
				continue
			}
		}
	}()
}

// 读取消息
func (class *WebsocketClient) readMsgThread() {
	go func() {
		for {
			if class.conn != nil {
				i9, message, err := class.conn.ReadMessage()
				if err != nil {
					//fmt.Println("read:", err)
					return
				}
				if i9 == 9 {
					//响应服务器主动发来的pong 表示我还在线
					class.conn.WriteControl(websocket.PongMessage, []byte{}, time.Now().Add(time.Second))
				}
				var messages map[string]string
				json.Unmarshal(message, &messages)
				fmt.Println(messages["message"])
				if len(messages["message"]) > 1 {
					if temp1 := strings.Index(messages["message"], class.user+"."); temp1 != -1 {
						if messages["message"] == class.user+".关机" {
							class.conn.WriteMessage(websocket.TextMessage, []byte("执行关机中..."+class.StartDate))
							//主动向服务端发送断开连接消息
							class.conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(4001, "close"), time.Now().Add(time.Second))
							time.Sleep(time.Millisecond * 100)
							class.ShutDown()
							return
						}
						x := WindowsAlert{}
						a := []rune(messages["message"])[6:]
						x.ShowMessage("弹窗提示", string(a))
					}
				}
			}

		}
	}()
	go func() {
		for {
			s := <-class.Ch
			switch s {
			case syscall.SIGINT:
				class.conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(4001, "close"), time.Now().Add(time.Millisecond*100))
				//fmt.Println("退出前执行")
			case syscall.SIGILL:
				//fmt.Println("null")
			default:
				//fmt.Println("default")
			}
		}
	}()
}

// 开启服务并重连
func (class *WebsocketClient) Start() {
	for {
		if !class.isAlive {
			class.dail(class.wtype, class.user, class.password, class.room)
			if class.isAlive {
				class.sendMsgThread()
				class.readMsgThread()
			}
		}
		time.Sleep(time.Second * time.Duration(class.timeout))
	}
}
func (class *WebsocketClient) ShutDown() {
	fmt.Println("关闭主机")
	arg := []string{"-s", "-t", "0"}
	cmd := exec.Command("shutdown", arg...)
	cmd.CombinedOutput()
}

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)
}
