package cbind

import (
	
	
	

	
)

// Modifier labels
const (
	LabelCtrl  = "ctrl"
	LabelAlt   = "alt"
	LabelMeta  = "meta"
	LabelShift = "shift"
)

// ErrInvalidKeyEvent is the error returned when encoding or decoding a key event fails.
var ErrInvalidKeyEvent = errors.New("invalid key event")

// UnifyEnterKeys is a flag that determines whether or not KPEnter (keypad
// enter) key events are interpreted as Enter key events. When enabled, Ctrl+J
// key events are also interpreted as Enter key events.
var UnifyEnterKeys = true

var fullKeyNames = map[string]string{
	"backspace2": "Backspace",
	"pgup":       "PageUp",
	"pgdn":       "PageDown",
	"esc":        "Escape",
}

var ctrlKeys = map[rune]tcell.Key{
	' ':  tcell.KeyCtrlSpace,
	'a':  tcell.KeyCtrlA,
	'b':  tcell.KeyCtrlB,
	'c':  tcell.KeyCtrlC,
	'd':  tcell.KeyCtrlD,
	'e':  tcell.KeyCtrlE,
	'f':  tcell.KeyCtrlF,
	'g':  tcell.KeyCtrlG,
	'h':  tcell.KeyCtrlH,
	'i':  tcell.KeyCtrlI,
	'j':  tcell.KeyCtrlJ,
	'k':  tcell.KeyCtrlK,
	'l':  tcell.KeyCtrlL,
	'm':  tcell.KeyCtrlM,
	'n':  tcell.KeyCtrlN,
	'o':  tcell.KeyCtrlO,
	'p':  tcell.KeyCtrlP,
	'q':  tcell.KeyCtrlQ,
	'r':  tcell.KeyCtrlR,
	's':  tcell.KeyCtrlS,
	't':  tcell.KeyCtrlT,
	'u':  tcell.KeyCtrlU,
	'v':  tcell.KeyCtrlV,
	'w':  tcell.KeyCtrlW,
	'x':  tcell.KeyCtrlX,
	'y':  tcell.KeyCtrlY,
	'z':  tcell.KeyCtrlZ,
	'\\': tcell.KeyCtrlBackslash,
	']':  tcell.KeyCtrlRightSq,
	'^':  tcell.KeyCtrlCarat,
	'_':  tcell.KeyCtrlUnderscore,
}

// Decode decodes a string as a key or combination of keys.
func ( string) ( tcell.ModMask,  tcell.Key,  rune,  error) {
	if len() == 0 {
		return 0, 0, 0, ErrInvalidKeyEvent
	}

	// Special case for plus rune decoding
	if [len()-1:] == "+" {
		 = tcell.KeyRune
		 = '+'

		if len() == 1 {
			return , , , nil
		} else if len() == 2 {
			return 0, 0, 0, ErrInvalidKeyEvent
		} else {
			 = [:len()-2]
		}
	}

	 := strings.Split(, "+")
:
	for ,  := range  {
		// Decode modifiers
		 := strings.ToLower()
		switch  {
		case LabelCtrl:
			 |= tcell.ModCtrl
			continue
		case LabelAlt:
			 |= tcell.ModAlt
			continue
		case LabelMeta:
			 |= tcell.ModMeta
			continue
		case LabelShift:
			 |= tcell.ModShift
			continue
		}

		// Decode key
		for ,  := range fullKeyNames {
			if  == strings.ToLower() {
				 = 
				break
			}
		}
		switch  {
		case "backspace":
			 = tcell.KeyBackspace2
			continue
		case "space", "spacebar":
			 = tcell.KeyRune
			 = ' '
			continue
		}
		for ,  := range tcell.KeyNames {
			if  == strings.ToLower(strings.ReplaceAll(, "-", "+")) {
				 = 
				if  < 0x80 {
					 = rune()
				}
				continue 
			}
		}

		// Decode rune
		if len() > 1 {
			return 0, 0, 0, ErrInvalidKeyEvent
		}

		 = tcell.KeyRune
		 = rune([0])
	}

	if &tcell.ModCtrl != 0 {
		,  := ctrlKeys[unicode.ToLower()]
		if  {
			 = 
			if UnifyEnterKeys &&  == ctrlKeys['j'] {
				 = tcell.KeyEnter
			} else if  < 0x80 {
				 = rune()
			}
		}
	}

	return , , , nil
}

// Encode encodes a key or combination of keys a string.
func ( tcell.ModMask,  tcell.Key,  rune) (string, error) {
	var  strings.Builder
	var  bool

	if &tcell.ModCtrl != 0 {
		if  == tcell.KeyBackspace ||  == tcell.KeyTab ||  == tcell.KeyEnter {
			 ^= tcell.ModCtrl
		} else {
			for ,  := range ctrlKeys {
				if  ==  {
					 ^= tcell.ModCtrl
					break
				}
			}
		}
	}

	if  != tcell.KeyRune {
		if UnifyEnterKeys &&  == ctrlKeys['j'] {
			 = tcell.KeyEnter
		} else if  < 0x80 {
			 = rune()
		}
	}

	// Encode modifiers
	if &tcell.ModCtrl != 0 {
		.WriteString(upperFirst(LabelCtrl))
		 = true
	}
	if &tcell.ModAlt != 0 {
		if  {
			.WriteRune('+')
		}
		.WriteString(upperFirst(LabelAlt))
		 = true
	}
	if &tcell.ModMeta != 0 {
		if  {
			.WriteRune('+')
		}
		.WriteString(upperFirst(LabelMeta))
		 = true
	}
	if &tcell.ModShift != 0 {
		if  {
			.WriteRune('+')
		}
		.WriteString(upperFirst(LabelShift))
		 = true
	}

	if  == tcell.KeyRune &&  == ' ' {
		if  {
			.WriteRune('+')
		}
		.WriteString("Space")
	} else if  != tcell.KeyRune {
		// Encode key
		 := tcell.KeyNames[]
		if  == "" {
			return "", ErrInvalidKeyEvent
		}
		 = strings.ReplaceAll(, "-", "+")
		 := fullKeyNames[strings.ToLower()]
		if  != "" {
			 = 
		}

		if  {
			.WriteRune('+')
		}
		.WriteString()
	} else {
		// Encode rune
		if  {
			.WriteRune('+')
		}
		.WriteRune()
	}

	return .String(), nil
}

func upperFirst( string) string {
	if len() <= 1 {
		return strings.ToUpper()
	}
	return strings.ToUpper([:1]) + [1:]
}