// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

// keystroke_test.go 测试按键解析功能
package shortcuts

import (
	"testing"

	"github.com/linuxdeepin/go-x11-client/util/keysyms"
	"github.com/stretchr/testify/assert"
)

// TestSplitKeystroke 测试按键字符串分割功能
// 验证splitKeystroke函数能否正确解析各种按键组合
func TestSplitKeystroke(t *testing.T) {
	var keys []string
	var err error
	keys, err = splitKeystroke("<Super>L")
	assert.NoError(t, err)
	assert.ElementsMatch(t, keys, []string{"Super", "L"})

	// 测试单个按键
	keys, err = splitKeystroke("<Super>")
	assert.NoError(t, err)
	assert.ElementsMatch(t, keys, []string{"Super"})

	keys, err = splitKeystroke("Super_L")
	assert.NoError(t, err)
	assert.ElementsMatch(t, keys, []string{"Super_L"})

	keys, err = splitKeystroke("<Shift><Super>T")
	assert.NoError(t, err)
	assert.ElementsMatch(t, keys, []string{"Shift", "Super", "T"})

	// 异常情况测试:
	_, err = splitKeystroke("<Super>>")  // 多余的>符号
	assert.Error(t, err)

	_, err = splitKeystroke("<Super><")  // 缺少结束>
	assert.Error(t, err)

	_, err = splitKeystroke("Super<")    // 无效的<位置
	assert.Error(t, err)

	_, err = splitKeystroke("<Super><shiftT")  // 不完整的修饰符
	assert.Error(t, err)

	_, err = splitKeystroke("<Super><Shift><>T")  // 空修饰符
	assert.Error(t, err)
}

// TestParseKeystroke 测试按键解析功能
// 验证ParseKeystroke函数能否正确解析各种按键组合
func TestParseKeystroke(t *testing.T) {
	var ks *Keystroke
	var err error

	// 测试单个按键（无修饰符）
	ks, err = ParseKeystroke("Super_L")
	assert.NoError(t, err)
	assert.Equal(t, ks, &Keystroke{
		Keystr: "Super_L",
		Keysym: keysyms.XK_Super_L,
	})

	// 测试特殊功能键
	ks, err = ParseKeystroke("Num_Lock")
	assert.NoError(t, err)
	assert.Equal(t, ks, &Keystroke{
		Keystr: "Num_Lock",
		Keysym: keysyms.XK_Num_Lock,
	})

	// 测试组合键（两个修饰符）
	ks, err = ParseKeystroke("<Control><Super>T")
	assert.NoError(t, err)
	assert.Equal(t, ks, &Keystroke{
		Keystr: "T",
		Keysym: keysyms.XK_T,
		Mods:   keysyms.ModMaskSuper | keysyms.ModMaskControl,
	})

	// 测试组合键（四个修饰符）
	ks, err = ParseKeystroke("<Control><Alt><Shift><Super>T")
	assert.NoError(t, err)
	assert.Equal(t, ks, &Keystroke{
		Keystr: "T",
		Keysym: keysyms.XK_T,
		Mods:   keysyms.ModMaskShift | keysyms.ModMaskSuper | keysyms.ModMaskAlt | keysyms.ModMaskControl,
	})

	// 异常情况测试:
	_, err = ParseKeystroke("<Shift>XXXXX")  // 无效按键名称
	assert.Error(t, err)

	_, err = ParseKeystroke("")  // 空字符串
	assert.Error(t, err)

	_, err = ParseKeystroke("<lock><Shift>A")  // 无效修饰符
	assert.Error(t, err)
}

// TestParseKeystrokes 测试批量解析按键功能
// 验证ParseKeystrokes函数能否正确处理多个按键字符串
func TestParseKeystrokes(t *testing.T) {
	keystrokes := []string{
		"<Super>S", "<Control>C",
		"<Alt>A", "<Control><Alt>V",
	}
	ret := ParseKeystrokes(keystrokes)
	assert.Equal(t, len(ret), len(keystrokes))
}

// TestKeystrokeMethodString 测试按键字符串表示方法
// 验证Keystroke的String方法能否正确生成按键字符串
func TestKeystrokeMethodString(t *testing.T) {
	var ks Keystroke

	// 测试特殊字符按键
	ks = Keystroke{
		Keystr: "percent",
		Mods:   keysyms.ModMaskControl | keysyms.ModMaskShift,
	}
	assert.Equal(t, ks.String(), "<Shift><Control>percent")

	// 测试字母按键
	ks = Keystroke{
		Keystr: "T",
		Mods:   keysyms.ModMaskShift | keysyms.ModMaskSuper | keysyms.ModMaskAlt | keysyms.ModMaskControl,
	}
	assert.Equal(t, ks.String(), "<Shift><Control><Alt><Super>T")
}

// TestParseLoopback 测试按键解析的循环一致性
// 验证按键字符串解析后重新生成的字符串是否一致
func TestParseLoopback(t *testing.T) {
	// 测试大写修饰符
	ks, err := ParseKeystroke("<SHIFT><CONTROL><ALT><SUPER>T")
	assert.NoError(t, err)
	assert.Equal(t, ks.String(), "<Shift><Control><Alt><Super>T")

	// 测试小写修饰符
	ks, err = ParseKeystroke("<shift><control><alt><super>t")
	assert.NoError(t, err)
	assert.Equal(t, ks.String(), "<Shift><Control><Alt><Super>t")
}

// TestParseMediaKey 测试媒体键解析功能
// 验证各种媒体按键能否正确解析
func TestParseMediaKey(t *testing.T) {
	keys := []string{
		"XF86Messenger",
		"XF86Save",
		"XF86New",
		"XF86WakeUp",
		"XF86AudioRewind",
		"XF86AudioMute",
		"XF86MonBrightnessUp",
		"XF86WLAN",
		"XF86AudioMedia",
		"XF86Reply",
		"XF86Favorites",
		"XF86AudioPlay",
		"XF86AudioMicMute",
		"XF86AudioPause",
		"XF86AudioStop",
		"XF86PowerOff",
		"XF86Documents",
		"XF86Game",
		"XF86Search",
		"XF86AudioRecord",
		"XF86Display",
		"XF86Reload",
		"XF86Explorer",
		"XF86Calculator",
		"XF86Calendar",
		"XF86Forward",
		"XF86Cut",
		"XF86MonBrightnessDown",
		"XF86Copy",
		"XF86Tools",
		"XF86AudioRaiseVolume",
		"XF86Close",
		"XF86WWW",
		"XF86HomePage",
		"XF86Sleep",
		"XF86AudioLowerVolume",
		"XF86AudioPrev",
		"XF86AudioNext",
		"XF86Paste",
		"XF86Open",
		"XF86Send",
		"XF86MyComputer",
		"XF86Mail",
		"XF86BrightnessAdjust",
		"XF86LogOff",
		"XF86Pictures",
		"XF86Terminal",
		"XF86Video",
		"XF86Music",
		"XF86ApplicationLeft",
		"XF86ApplicationRight",
		"XF86Meeting",
	}

	for _, key := range keys {
		ks, err := ParseKeystroke(key)
		assert.NoError(t, err)
		assert.Equal(t, ks.String(), key)
	}
}
