package history

import (
	
	
)

// lineHistory contains all state changes for a given input line,
// whether it is the current input line or one of the history ones.
type lineHistory struct {
	pos   int
	items []undoItem
}

type undoItem struct {
	line string
	pos  int
}

// Save saves the current line and cursor position as an undo state item.
// If this was called while the shell was in the middle of its undo history
// (eg. the caller has undone one or more times), all undone steps are dropped.
func ( *Sources) () {
	defer .Reset()

	if .skip {
		return
	}

	// Get the undo states for the current line.
	 := .getLineHistory()
	if  == nil {
		return
	}

	// When the line is identical to the previous undo, we just update
	// the cursor position if it's a different one.
	if len(.items) > 0 && .items[len(.items)-1].line == string(*.line) {
		.items[len(.items)-1].pos = .cursor.Pos()
		return
	}

	// When we add an item to the undo history, the history
	// is cut from the current undo hist position onwards.
	if .pos > len(.items) {
		.pos = len(.items)
	}

	.items = .items[:len(.items)-.pos]

	// Make a copy of the cursor and ensure its position.
	 := core.NewCursor(.line)
	.Set(.cursor.Pos())
	.CheckCommand()

	// And save the item.
	.items = append(.items, undoItem{
		line: string(*.line),
		pos:  .Pos(),
	})
}

// SkipSave will not save the current line when the target command is done
// (more precisely, the next call to h.Save() will have no effect).
// This function is not useful is most cases, as call to saves will efficiently
// compare the line with the last saved state, and will not add redundant ones.
func ( *Sources) () {
	.skip = true
}

// SaveWithCommand is only meant to be called in the main readline loop of the shell,
// and not from within commands themselves: it does the same job as Save(), but also
// keeps the command that has just been executed.
func ( *Sources) ( inputrc.Bind) {
	.last = 
	.Save()
}

// Undo restores the line and cursor position to their last saved state.
func ( *Sources) () {
	.skip = true
	.undoing = true

	// Get the undo states for the current line.
	 := .getLineHistory()
	if  == nil || len(.items) == 0 {
		return
	}

	var  undoItem

	// When undoing, we loop through preceding undo items
	// as long as they are identical to the current line.
	for {
		.pos++

		// Exit if we reached the end.
		if .pos > len(.items) {
			.pos = len(.items)
			return
		}

		// Break as soon as we find a non-matching line.
		 = .items[len(.items)-.pos]
		if .line != string(*.line) {
			break
		}
	}

	// Use the undo we found
	.line.Set([]rune(.line)...)
	.cursor.Set(.pos)
}

// Revert goes back to the initial state of the line, which is what it was
// like when the shell started reading user input. Note that this state might
// be a line that was inferred, accept-and-held from the previous readline run.
func ( *Sources) () {
	 := .getLineHistory()
	if  == nil || len(.items) == 0 {
		return
	}

	// Reuse the first saved state.
	 := .items[0]

	.line.Set([]rune(.line)...)
	.cursor.Set(.pos)

	// And reset everything
	.items = make([]undoItem, 0)

	.Reset()
}

// Redo cancels an undo action if any has been made, or if
// at the begin of the undo history, restores the original
// line's contents as their were before starting undoing.
func ( *Sources) () {
	.skip = true
	.undoing = true

	 := .getLineHistory()
	if  == nil || len(.items) == 0 {
		return
	}

	.pos--

	if .pos < 1 {
		return
	}

	 := .items[len(.items)-.pos]
	.line.Set([]rune(.line)...)
	.cursor.Set(.pos)
}

// Last returns the last command ran by the shell.
func ( *Sources) () inputrc.Bind {
	return .last
}

// Pos returns the current position in the undo history, which is
// equal to its length minus the number of previous undo calls.
func ( *Sources) () int {
	 := .getLineHistory()
	if  == nil {
		return 0
	}

	return .pos
}

// Reset will reset the current position in the list
// of undo items, but will not delete any of them.
func ( *Sources) () {
	.skip = false

	 := .getLineHistory()
	if  == nil {
		return
	}

	if !.undoing {
		.pos = 0
	}

	.undoing = false
}

// Always returns a non-nil map, whether or not a history source is found.
func ( *Sources) () map[int]*lineHistory {
	 := .Current()
	if  == nil {
		return map[int]*lineHistory{}
	}

	// Get the state changes of all history lines
	// for the current history source.
	 := .names[.sourcePos]

	 := .lines[]
	if  == nil {
		.lines[] = make(map[int]*lineHistory)
		 = .lines[]
	}

	return 
}

func ( *Sources) () *lineHistory {
	 := .getHistoryLineChanges()
	if  == nil {
		return &lineHistory{}
	}

	// Compute the position of the current line in the history.
	 := -1

	 := .Current()
	if .hpos > -1 &&  != nil {
		 = .Len() - .hpos
	}

	if [] == nil {
		[] = &lineHistory{}
	}

	// Return the state changes of the current line.
	return []
}

func ( *Sources) () {
	.hpos = -1

	 := .getHistoryLineChanges()
	if  == nil {
		return
	}

	// Get the undo states for the line buffer
	// (the last one, not any of the history ones)
	 := [.hpos]
	if  == nil || len(.items) == 0 {
		return
	}

	 := .items[len(.items)-1]

	// Restore the line to the last known state.
	.line.Set([]rune(.line)...)
	.cursor.Set(.pos)
}