package editor

import (
	
	
	
	
	
	

	
	
)

var (
	// validRegisterKeys - All valid register IDs (keys) for read/write Vim registers.
	// validRegisterKeys = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-\"".

	numRegisters   = 10
	alphaRegisters = 52
)

// Buffers is a list of registers in which to put yanked/cut contents.
// These buffers technically are Vim registers with full functionality.
type Buffers struct {
	num      map[int][]rune  // numbered registers (0-9)
	alpha    map[rune][]rune // lettered registers ( a-z )
	ro       map[rune][]rune // read-only registers ( . % : )
	waiting  bool            // The user wants to use a still unidentified register
	selected bool            // We have identified the register, and acting on it.
	active   rune            // Any of the read/write registers ("/num/alpha)
	mutex    *sync.Mutex
}

// NewBuffers is a required constructor to set up all the buffers/registers
// for the shell, because it contains maps that must be correctly initialized.
func () *Buffers {
	return &Buffers{
		num:   make(map[int][]rune, numRegisters),
		alpha: make(map[rune][]rune, alphaRegisters),
		ro:    map[rune][]rune{},
		mutex: &sync.Mutex{},
	}
}

// SetActive sets the currently active register/buffer.
// Valid values are letters (lower/upper), digits (1-9),
// or read-only buffers ( . % : ).
func ( *Buffers) ( rune) {
	defer func() {
		// We now have an active, identified register
		.waiting = false
		.selected = true
	}()

	// Numbered
	,  := strconv.Atoi(string())
	if  == nil &&  < 10 {
		.active = 
		return
	}
	// Read-only
	if ,  := .ro[];  {
		.active = 

		return
	}

	// Else, lettered
	.active = 
}

// Get returns the contents of a given register.
// If the rune is nil (rune(0)), it returns the value of the kill buffer (the " Vim register).
// If the rune is an alphanumeric comprised in the valid register IDs, their content is returned.
// If the register name is invalid, the function returns an empty rune slice.
func ( *Buffers) ( rune) []rune {
	if  == 0 {
		return .GetKill()
	}

	,  := strconv.Atoi(string())
	if  == nil {
		return .num[]
	}

	if ,  := .alpha[];  {
		return 
	}

	if ,  := .ro[];  {
		return 
	}

	return nil
}

// Active returns the contents of the active buffer/register (or the kill
// buffer if no active register is active), and resets the active register.
func ( *Buffers) () []rune {
	defer .Reset()

	if !.waiting && !.selected {
		return .GetKill()
	}

	return .Get(.active)
}

// Pop rotates the kill ring and returns the new top.
func ( *Buffers) () []rune {
	if len(.num) == 0 {
		return nil
	}

	// Reassign the kill buffer and
	// pop the first numbered register.
	 := string(.num[0])
	delete(.num, 0)

	for  := 0;  < len(.num); ++ {
		.num[] = []rune(string(.num[+1]))
		delete(.num, +1)
	}

	return []rune()
}

// GetKill returns the contents of the kill buffer.
func ( *Buffers) () []rune {
	if len(.num) == 0 {
		return nil
	}

	return .num[0]
}

// Write writes a slice to the currently active buffer, and/or to the kill one.
// After the operation, the buffers are reset, eg. none is considered active.
func ( *Buffers) ( ...rune) {
	 := string()

	defer .Reset()

	if len() == 0 ||  == "" {
		return
	}

	// Either write to the active register, or add to numbered ones.
	if .selected {
		.WriteTo(.active, []rune()...)
	} else {
		.writeNum(-1, []rune())
	}
}

// WriteTo writes a slice directly to a target register.
// If the register name is invalid, nothing is written anywhere.
func ( *Buffers) ( rune,  ...rune) {
	 := string()

	if len() == 0 ||  == "" {
		return
	}

	if  == 0 {
		.writeNum(0, []rune())
		return
	}

	// If number register.
	,  := strconv.Atoi(string())
	if  > 0 &&  < 10 &&  != nil {
		.writeNum(, []rune())
		return
	}

	// If lettered register.
	if unicode.IsLetter() {
		.writeAlpha(, []rune())
		return
	}
}

// IsSelected returns the name of the selected register, and
// true if one is indeed selected, or the default one and false.
func ( *Buffers) () ( string,  bool) {
	return string(.active), .selected
}

// Reset forgets any active/pending buffer/register, but does not delete its contents.
func ( *Buffers) () {
	.active = 0
	.waiting = false
	.selected = false
}

// Complete returns the contents of all buffers as a structured list of completions.
func ( *Buffers) () completion.Values {
	 := make([]completion.Candidate, 0)

	// Alpha and numbered registers
	 = append(, .completeNumRegs()...)
	 = append(, .completeAlphaRegs()...)

	// Disable sorting, force list long and add hint.
	 := completion.AddRaw()
	if .NoSort == nil {
		.NoSort = make(map[string]bool)
	}

	.NoSort["*"] = true

	if .ListLong == nil {
		.ListLong = make(map[string]bool)
	}

	.ListLong["*"] = true

	// Registers Hint
	 := color.Bold + color.FgBlue + "(registers)"

	if len() == 0 {
		 += " - empty -"
	}

	.Messages.Add()

	return 
}

func ( *Buffers) ( int,  []rune) {
	// No numbered register above 10
	if  > numRegisters-1 {
		return
	}

	// Add to the stack with the specified register
	if  > 0 {
		.num[] = 

		return
	}

	// No push to the stack if we are already using 9
	for  := len(.num);  > 0; -- {
		if  == numRegisters {
			--
		}

		.num[] = append([]rune{}, .num[-1]...)
	}

	.num[0] = append([]rune{}, ...)
}

func ( *Buffers) ( rune,  []rune) {
	 := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	 := false

	for ,  := range  {
		if  ==  {
			 = unicode.ToLower(.active)
			,  := .alpha[]

			if  {
				.alpha[] = append(.alpha[], ...)
			} else {
				.alpha[] = 
			}

			 = true
		}
	}

	if ! {
		.alpha[] = 
	}
}

func ( *Buffers) () []completion.Candidate {
	 := make([]completion.Candidate, 0)
	 := color.Dim + "num ([0-9])" + color.Reset

	var  []int
	for  := range .num {
		 = append(, )
	}

	sort.Ints()

	for ,  := range  {
		 := .num[]
		 := strings.ReplaceAll(string(), "\n", ` `)

		 := completion.Candidate{
			Tag:     ,
			Value:   string(),
			Display: fmt.Sprintf("%s\"%d%s %s", color.Dim, , color.DimReset, ),
		}

		 = append(, )
	}

	return 
}

func ( *Buffers) () []completion.Candidate {
	 := make([]completion.Candidate, 0)
	 := color.Dim + "alpha ([a-z], [A-Z])" + color.Reset

	var  []rune
	for  := range .alpha {
		 = append(, )
	}

	sort.Slice(, func(,  int) bool { return  <  })

	for ,  := range  {
		 := .alpha[]
		 := strings.ReplaceAll(string(), "\n", ` `)

		 := completion.Candidate{
			Tag:     ,
			Value:   string(),
			Display: fmt.Sprintf("%s\"%s%s %s", color.Dim, string(), color.DimReset, ),
		}

		 = append(, )
	}

	return 
}