package strutil

import (
	
	
	
	
	
	
	
)

const (
	// Max integer value on 64 bit architecture.
	maxInt = 9223372036854775807
)

// KeywordSwitcher is a function modifying a given word, returning:
// @done     => If true, the handler performed a change.
// @switched => The updated word.
// @bpos     => Offset to begin position.
// @epos     => Offset to end position.
type KeywordSwitcher func(word string, increase bool, times int) (done bool, switched string, bpos, epos int)

// KeywordSwitchers returns all keywordSwitchers of the shell.
func () []KeywordSwitcher {
	return []KeywordSwitcher{
		switchNumber,
		switchBoolean,
		switchWeekday,
		switchOperator,
	}
}

// AdjustNumberOperatorPos returns an adjusted cursor position when
// the word around the cursor is an expression with an operator.
func ( int,  []rune) int {
	 := lineSlice(, , 2)

	if ,  := regexp.MatchString(`[+-][0-9]`, );  {
		// If cursor is on the `+` or `-`, we need to check if it is a
		// number with a sign or an operator, only the number needs to
		// forward the cursor.
		 := regexp.MustCompile(`[^0-9]`)
		if  == 0 || .MatchString(string([-1])) {
			++
		}
	} else if ,  := regexp.MatchString(`[+-][a-zA-Z]`, );  {
		// If cursor is on the `+` or `-`, we need to check if it is a
		// short option, only the short option needs to forward the cursor.
		if  == 0 || [-1] == ' ' {
			++
		}
	}

	return 
}

// lineSlice returns a subset of the current input line.
func lineSlice( []rune, ,  int) ( string) {
	switch {
	case + > len():
		 = string([:])
	case  < 0:
		if + < 0 {
			 = string([:])
		} else {
			 = string([+ : ])
		}
	default:
		 = string([ : +])
	}

	return
}

func switchNumber( string,  bool,  int) ( bool,  string, ,  int) {
	if , , ,  = switchHexa(, );  {
		return
	}

	if , , ,  = switchBinary(, );  {
		return
	}

	if , , ,  = switchDecimal(, );  {
		return
	}

	return
}

// Hexadecimal cases:
//
// 1. Increment:
// 0xDe => 0xdf
// 0xdE => 0xDF
// 0xde0 => 0xddf
// 0xffffffffffffffff => 0x0000000000000000
// 0X9 => 0XA
// 0Xdf => 0Xe0
//
// 2. Decrement:
// 0xdE0 => 0xDDF
// 0xffFf0 => 0xfffef
// 0xfffF0 => 0xFFFEF
// 0x0 => 0xffffffffffffffff
// 0X0 => 0XFFFFFFFFFFFFFFFF
// 0Xf => 0Xe.
func switchHexa( string,  int) ( bool,  string, ,  int) {
	 := regexp.MustCompile(`[^0-9]?(0[xX][0-9a-fA-F]*)`)
	 := .FindString()

	if  == "" {
		return
	}

	 = true

	 := 
	 := [:2]
	 := [len():]
	 := .FindStringIndex()
	,  := [0], [1]
	,  = , 

	if ,  := regexp.MatchString(`[A-Z][0-9]*$`, ); ! {
		 = strings.ToUpper()
	}

	,  := strconv.ParseInt(, 16, 64)
	if  != nil {
		 = false
		return
	}

	 := big.NewInt(maxInt)
	 := big.NewInt()
	 := big.NewInt(int64())
	 := .Add(, )

	 := 

	switch {
	case .Cmp(big.NewInt(0)) < 0:
		 := .Sub(, .Abs())
		if .IsInt64() {
			 = .Int64()
		} else {
			 = math.MaxInt64
		}
	case .CmpAbs() >= 0:
		 := .Sub(, )
		if .IsInt64() {
			 = .Int64()
		} else {
			 = int64() - ( - )
		}
	default:
		 = .Int64()
	}

	 = fmt.Sprintf("%x", )
	 =  + 

	return , , , 
}

// Binary cases:
//
// 1. Increment:
// 0b1 => 0b10
// 0x1111111111111111111111111111111111111111111111111111111111111111 =>
// 0x0000000000000000000000000000000000000000000000000000000000000000
// 0B0 => 0B1
//
// 2. Decrement:
// 0b1 => 0b0
// 0b100 => 0b011
// 0B010 => 0B001
// 0b0 =>
// 0x1111111111111111111111111111111111111111111111111111111111111111.
func switchBinary( string,  int) ( bool,  string, ,  int) {
	 := regexp.MustCompile(`[^0-9]?(0[bB][01]*)`)
	 := .FindString()

	if  == "" {
		return
	}

	 = true

	 := 
	 := [:2]
	 := [len():]
	 := .FindStringIndex()
	,  := [0], [1]
	,  = , 

	,  := strconv.ParseInt(, 2, 64)
	if  != nil {
		 = false
		return
	}

	 := big.NewInt(maxInt)
	 := big.NewInt()
	 := big.NewInt(int64())
	 := .Add(, )
	 := big.NewInt(0)

	 := 

	switch {
	case .Cmp() < 0:
		 := .Sub(, .Abs())
		if .IsInt64() {
			 = .Int64()
		} else {
			 = math.MaxInt64
		}
	case .CmpAbs() >= 0:
		 := .Sub(, )
		if .IsInt64() {
			 = .Int64()
		} else {
			 = int64() - ( - )
		}
	default:
		 = .Int64()
	}

	 = fmt.Sprintf("%b", )
	 =  + 

	return , , , 
}

// Decimal cases:
//
// 1. Increment:
// 0 => 1
// 99 => 100
//
// 2. Decrement:
// 0 => -1
// 10 => 9
// aa1230xa => aa1231xa // NOT WORKING => MATCHED BY HEXA
// aa1230bb => aa1231bb
// aa123a0bb => aa124a0bb.
func switchDecimal( string,  int) ( bool,  string, ,  int) {
	 := regexp.MustCompile(`([-+]?[0-9]+)`)
	 := .FindString()

	if  == "" {
		return
	}

	 = true

	 := .FindStringIndex()
	,  := [0], [1]
	,  = , 

	,  := strconv.Atoi()
	 += 

	 = strconv.Itoa()

	// Add prefix if needed
	if [0] == '+' {
		 = "+" + 
	}

	// Don't consider anything done if result is empty.
	if  == "" {
		 = false
	}

	return
}

func switchBoolean( string,  bool,  int) ( bool,  string, ,  int) {
	 = len()

	 := regexp.MustCompile(`(^[+-]{0,2})`)
	if  := .FindString();  != "" {
		 := .FindStringIndex()
		 = [1]
		 = [:]
	}

	 := map[string]string{
		"true":  "false",
		"false": "true",
		"t":     "f",
		"f":     "t",
		"yes":   "no",
		"no":    "yes",
		"y":     "n",
		"n":     "y",
		"on":    "off",
		"off":   "on",
	}

	,  = [strings.ToLower()]
	if ! {
		return
	}

	 = true

	// Transform case
	if ,  := regexp.MatchString(`^[A-Z]+$`, );  {
		 = strings.ToLower()
	} else if ,  := regexp.MatchString(`^[A-Z]`, );  {
		 := [0]
		 := unicode.ToUpper(rune())
		 = string() + [1:]
	}

	return , , , 
}

func switchWeekday( string,  bool,  int) ( bool,  string, ,  int) {
	return
}

func switchOperator( string,  bool,  int) ( bool,  string, ,  int) {
	 = len()

	 := map[string]string{
		"&&":  "||",
		"||":  "&&",
		"++":  "--",
		"--":  "++",
		"==":  "!=",
		"!=":  "==",
		"===": "!==",
		"!==": "===",
		"+":   "-",
		"-":   "*",
		"*":   "/",
		"/":   "+",
		"and": "or",
		"or":  "and",
	}

	,  = [strings.ToLower()]
	if ! {
		return
	}

	 = true

	// Transform case
	if ,  := regexp.MatchString(`^[A-Z]+$`, );  {
		 = strings.ToLower()
	} else if ,  := regexp.MatchString(`^[A-Z]`, );  {
		 := [0]
		 := unicode.ToUpper(rune())
		 = string() + [1:]
	}

	return , , , 
}