package completion

import (
	

	
	
	
)

// IsearchStart starts incremental search (fuzzy-finding)
// with values matching the isearch minibuffer as a regexp.
func ( *Engine) ( string, ,  bool) {
	// Prepare all buffers and cursors.
	.isearchInsert = 
	.isearchReplaceLine = 

	.isearchStartBuf = string(*.line)
	.isearchStartCursor = .cursor.Pos()

	.isearchBuf = new(core.Line)
	.isearchCur = core.NewCursor(.isearchBuf)

	// Prepare all keymaps and modes.
	.auto = true
	.keymap.SetLocal(keymap.Isearch)
	.adaptIsearchInsertMode()

	// Hints
	.isearchName = 
	.hint.Set(color.Bold + color.FgCyan + .isearchName + " (isearch): " + color.Reset + string(*.isearchBuf))
}

// IsearchStop exists the incremental search mode,
// and drops the currently used regexp matcher.
// If revertLine is true, the original line is restored.
func ( *Engine) ( bool) {
	// Reset all buffers and cursors.
	.isearchBuf = nil
	.IsearchRegex = nil
	.isearchCur = nil

	// Reset the original line when needed.
	if .isearchReplaceLine &&  {
		.line.Set([]rune(.isearchStartBuf)...)
		.cursor.Set(.isearchStartCursor)
	}

	.isearchStartBuf = ""
	.isearchStartCursor = 0
	.isearchReplaceLine = false

	// And clear all related completion keymaps/modes.
	.auto = false
	.autoForce = false
	.keymap.SetLocal("")
	.resetIsearchInsertMode()
}

// GetBuffer returns the correct input line buffer (and its cursor/
// selection) depending on the context and active components:
// - If in non/incremental-search mode, the minibuffer.
// - If a completion is currently inserted, the completed line.
// - If neither of the above, the normal input line.
func ( *Engine) () (*core.Line, *core.Cursor, *core.Selection) {
	// Non/Incremental search buffer
	, ,  := .NonIncrementallySearching()

	if .keymap.Local() == keymap.Isearch ||  {
		 := core.NewSelection(.isearchBuf, .isearchCur)
		return .isearchBuf, .isearchCur, 
	}

	// Completed line (with inserted candidate)
	if len(.selected.Value) > 0 {
		return .compLine, .compCursor, .selection
	}

	// Or completer inactive, normal input line.
	return .line, .cursor, .selection
}

// UpdateIsearch recompiles the isearch buffer as a regex and
// filters matching candidates in the available completions.
func ( *Engine) () {
	, ,  := .NonIncrementallySearching()

	if .keymap.Local() != keymap.Isearch && ! {
		return
	}

	// If we have a virtually inserted candidate, it's because the
	// last action was a tab-complete selection: we don't need to
	// refresh the list of matches, as the minibuffer did not change,
	// and because it would make our currently selected comp to drop.
	if len(.selected.Value) > 0 {
		return
	}

	// Update helpers depending on the search/minibuffer mode.
	if .keymap.Local() == keymap.Isearch {
		.updateIncrementalSearch()
	} else {
		.updateNonIncrementalSearch()
	}
}

// NonIsearchStart starts a non-incremental, fake search mode:
// it does not produce or tries to match against completions,
// but uses a minibuffer similarly to incremental search mode.
func ( *Engine) ( string, , ,  bool) {
	if  {
		.isearchBuf = new(core.Line)
		.isearchBuf.Set([]rune(.isearchLast)...)
	} else {
		.isearchBuf = new(core.Line)
	}

	.isearchCur = core.NewCursor(.isearchBuf)
	.isearchCur.Set(.isearchBuf.Len())

	.isearchName = 
	.isearchForward = 
	.isearchSubstring = 

	.keymap.NonIncrementalSearchStart()
	.adaptIsearchInsertMode()
}

// NonIsearchStop exits the non-incremental search mode.
func ( *Engine) () {
	.isearchLast = string(*.isearchBuf)
	.isearchBuf = nil
	.IsearchRegex = nil
	.isearchCur = nil
	.isearchForward = false
	.isearchSubstring = false

	// Reset keymap and helpers
	.keymap.NonIncrementalSearchStop()
	.resetIsearchInsertMode()
	.hint.Reset()
}

// NonIncrementallySearching returns true if the completion engine
// is currently using a minibuffer for non-incremental search mode.
func ( *Engine) () (, ,  bool) {
	 = .isearchCur != nil && .keymap.Local() != keymap.Isearch
	 = .isearchForward
	 = .isearchSubstring

	return
}

func ( *Engine) () {
	var  string
	if hasUpper(*.isearchBuf) {
		 = string(*.isearchBuf)
	} else {
		 = "(?i)" + string(*.isearchBuf)
	}

	var  error

	.IsearchRegex,  = regexp.Compile()
	if  != nil {
		.hint.Set(color.FgRed + "Failed to compile i-search regexp")
	}

	// Refresh completions with the current minibuffer as a filter.
	.GenerateWith(.cached)

	// And filter out the completions.
	for ,  := range .groups {
		.updateIsearch()
	}

	// Update the hint section.
	 := color.Bold + color.FgCyan + .isearchName + " (inc-search)"

	if .Matches() == 0 {
		 += color.Reset + color.Bold + color.FgRed + " (no matches)"
	}

	 += ": " + color.Reset + color.Bold + string(*.isearchBuf) + color.Reset + "_"

	.hint.Set()

	// And update the inserted candidate if autoinsert is enabled.
	if .isearchInsert && .Matches() > 0 && .isearchBuf.Len() > 0 {
		// History incremental searches must replace the whole line.
		if .isearchReplaceLine {
			.prefix = ""
			.line.Set()
			.cursor.Set(0)
		}

		.Select(1, 0)
	} else if .isearchReplaceLine {
		// Else no matches, restore the original line.
		.line.Set([]rune(.isearchStartBuf)...)
		.cursor.Set(.isearchStartCursor)
	}
}

func ( *Engine) () {
	 := color.Bold + color.FgCyan + .isearchName +
		" (non-inc-search): " + color.Reset + color.Bold + string(*.isearchBuf) + color.Reset + "_"
	.hint.Set()
}

func ( *Engine) () {
	.isearchModeExit = .keymap.Main()

	if !.keymap.IsEmacs() && .keymap.Main() != keymap.ViInsert {
		.keymap.SetMain(keymap.ViInsert)
	}
}

func ( *Engine) () {
	if .isearchModeExit == "" {
		return
	}

	if .keymap.Main() != .isearchModeExit {
		.keymap.SetMain(string(.isearchModeExit))
		.isearchModeExit = ""
	}

	if .keymap.Main() == keymap.ViCommand {
		.cursor.CheckCommand()
	}
}