package wol

import (
	"bytes"
	"encoding/hex"
	"net"
	"regexp"
	"strings"
	"testing"
)

func TestRegExp(t *testing.T) {
	validateMac := func() func(mac string) bool {
		exp, _ := regexp.Compile("([0-9a-fA-F]{2}(-|:)?){5}([a-fA-F0-9]{2})")
		return func(mac string) bool {
			macLen := len(mac)
			return exp.MatchString(mac) && (macLen == 12 || macLen == 17)
		}
	}()

	t.Logf("255.255.255.255 %t", validateMac("255.255.255.255"))
	t.Logf("FF:FF:FF:FF:FF:FF %t", validateMac("FF:FF:FF:FF:FF:FF"))
	t.Logf("00-E0-4C-84-50-EB %t", validateMac("00-E0-4C-84-50-EB"))
	t.Logf("00E04C8450EB %t", validateMac("00E04C8450EB"))
	t.Logf("00E04C8450EBA %t", validateMac("00E04C8450EBA"))
}

func TestWol(t *testing.T) {
	udpAddr, err := net.ResolveUDPAddr("udp", "255.255.255.255:9")
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("%v", udpAddr)

	interfaces, err := net.Interfaces()
	if err != nil {
		t.Fatal(err)
	}

	mac := "00-E0-4C-84-50-EB"
	mac = strings.Replace(strings.Replace(mac, ":", "", -1), "-", "", -1)
	macHex, _ := hex.DecodeString(mac)
	// 广播MAC地址 FF:FF:FF:FF:FF:FF
	var broadcast = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
	var buffer bytes.Buffer
	buffer.Write(broadcast)
	for i := 0; i < 16; i++ {
		buffer.Write(macHex)
	}
	wolPackage := buffer.Bytes()

	for _, i := range interfaces {
		if i.Flags&net.FlagUp == 0 {
			t.Logf("%s 未启用", i.Name)
			continue
		}

		t.Logf("%s 已启用", i.Name)
		addrs, err := i.Addrs()
		if err != nil {
			t.Fatal(err)
		}

		for _, addr := range addrs {
			if ip, ok := addr.(*net.IPNet); ok {
				if ipv4 := ip.IP.To4(); ipv4 != nil {
					t.Logf("\t ipv4: %s", ipv4.String())

					conn, err := net.DialUDP("udp", &net.UDPAddr{IP: ipv4}, udpAddr)
					defer func() {
						_ = conn.Close()
					}()

					if err != nil {
						t.Errorf("wol 幻数据包发送失败 %s", err)
					}
					_, _ = conn.Write(wolPackage)
					t.Logf("wol 幻数据包发送成功, %s %s %s", i.Name, ipv4.String(), mac)
				}
			}
		}
	}
}

func TestWOLService(t *testing.T) {
	var service *Service
	err := service.WakeUp("00-E0-4C-84-50-EB", 9)
	if err != nil {
		t.Fatal(err)
	}
	t.Log("wol 唤醒成功")
}
