// Copyright 2026 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tcell

import "testing"

func TestEventKeyNameSidedModifiers(t *testing.T) {
	tests := []struct {
		key  Key
		mod  ModMask
		want string
	}{
		{KeyShift, ModLShift, "LeftShift"},
		{KeyShift, ModRShift, "RightShift"},
		{KeyCtrl, ModLCtrl, "LeftCtrl"},
		{KeyCtrl, ModRCtrl, "RightCtrl"},
		{KeyAlt, ModLAlt, "LeftAlt"},
		{KeyAlt, ModRAlt, "RightAlt"},
		{KeyMeta, ModLMeta, "LeftMeta"},
		{KeyMeta, ModRMeta, "RightMeta"},
		{KeyHyper, ModLHyper, "LeftHyper"},
		{KeyHyper, ModRHyper, "RightHyper"},
		{KeyShift, ModShift, "Shift"},
		{KeyCtrl, ModCtrl, "Ctrl"},
		{KeyAlt, ModAlt, "Alt"},
		{KeyMeta, ModMeta, "Meta"},
		{KeyHyper, ModHyper, "Hyper"},
	}

	for _, tt := range tests {
		ev := NewEventKeyEx(tt.key, "", tt.mod, true, tt.key, 1)
		if got := ev.Name(); got != tt.want {
			t.Errorf("Name() = %q, want %q", got, tt.want)
		}
	}
}

func TestEventKeyAdvancedNormalization(t *testing.T) {
	tests := []struct {
		name         string
		ev           *EventKey
		wantKey      Key
		wantStr      string
		wantMod      ModMask
		wantPressed  bool
		wantPhysical Key
		wantRepeat   int
	}{
		{
			name:         "advanced ctrl letter",
			ev:           NewEventKeyEx(KeyRune, "a", ModCtrl, false, KeyA, 0),
			wantKey:      KeyRune,
			wantStr:      "a",
			wantMod:      ModCtrl,
			wantPressed:  false,
			wantPhysical: KeyA,
			wantRepeat:   1,
		},
		{
			name:         "advanced shift tab",
			ev:           NewEventKeyEx(KeyTab, "", ModShift, true, KeyTab, 2),
			wantKey:      KeyTab,
			wantStr:      "",
			wantMod:      ModShift,
			wantPressed:  true,
			wantPhysical: KeyTab,
			wantRepeat:   2,
		},
		{
			name:         "advanced backtab normalizes to shift tab",
			ev:           NewEventKeyEx(KeyBacktab, "", ModNone, true, KeyBacktab, 1),
			wantKey:      KeyTab,
			wantStr:      "",
			wantMod:      ModShift,
			wantPressed:  true,
			wantPhysical: KeyTab,
			wantRepeat:   1,
		},
		{
			name:         "backspace alias",
			ev:           NewEventKeyEx(KeyBackspace2, "", ModNone, true, KeyBackspace2, 1),
			wantKey:      KeyBackspace,
			wantStr:      "",
			wantMod:      ModNone,
			wantPressed:  true,
			wantPhysical: KeyBackspace2,
			wantRepeat:   1,
		},
		{
			name:         "legacy shift printable normalizes",
			ev:           NewEventKey(KeyRune, "A", ModShift),
			wantKey:      KeyRune,
			wantStr:      "A",
			wantMod:      ModNone,
			wantPressed:  true,
			wantPhysical: 0,
			wantRepeat:   1,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if tt.ev.Key() != tt.wantKey || tt.ev.Str() != tt.wantStr ||
				tt.ev.Modifiers() != tt.wantMod || tt.ev.Pressed() != tt.wantPressed ||
				tt.ev.Physical() != tt.wantPhysical || tt.ev.Repeat() != tt.wantRepeat {
				t.Fatalf("unexpected event: key=%v str=%q mod=%v pressed=%v physical=%v repeat=%v",
					tt.ev.Key(), tt.ev.Str(), tt.ev.Modifiers(), tt.ev.Pressed(), tt.ev.Physical(), tt.ev.Repeat())
			}
		})
	}
}

func TestPhysicalKeyAliases(t *testing.T) {
	if KeyA != Key('a') || KeyZ != Key('z') || Key0 != Key('0') || Key9 != Key('9') || KeySpace != Key(' ') {
		t.Fatalf("physical key aliases do not match their rune values")
	}
	tests := []struct {
		name string
		key  Key
		want Key
	}{
		{"grave", KeyGrave, Key('`')},
		{"minus", KeyMinus, Key('-')},
		{"equal", KeyEqual, Key('=')},
		{"left bracket", KeyLBracket, Key('[')},
		{"right bracket", KeyRBracket, Key(']')},
		{"backslash", KeyBackslash, Key('\\')},
		{"semicolon", KeySemicolon, Key(';')},
		{"quote", KeyQuote, Key('\'')},
		{"comma", KeyComma, Key(',')},
		{"period", KeyPeriod, Key('.')},
		{"slash", KeySlash, Key('/')},
	}
	for _, tt := range tests {
		if tt.key != tt.want {
			t.Fatalf("%s key alias = %v, want %v", tt.name, tt.key, tt.want)
		}
	}
}

func TestPhysicalKeySlashLogicalText(t *testing.T) {
	unshifted := NewEventKeyEx(KeyRune, "/", ModNone, true, KeySlash, 1)
	if unshifted.Str() != "/" || unshifted.Physical() != KeySlash {
		t.Fatalf("unshifted slash: str=%q physical=%v", unshifted.Str(), unshifted.Physical())
	}

	shifted := NewEventKeyEx(KeyRune, "?", ModShift, true, KeySlash, 1)
	if shifted.Str() != "?" || shifted.Physical() != KeySlash {
		t.Fatalf("shifted slash: str=%q physical=%v", shifted.Str(), shifted.Physical())
	}
}
