package mode

import (
	

	
	
	
	
)

// Histlist is a mode for browsing history and selecting entries to insert. It
// is based on the ComboBox widget.
type Histlist interface {
	tk.ComboBox
}

// HistlistSpec specifies the configuration for the histlist mode.
type HistlistSpec struct {
	// Key bindings.
	Bindings tk.Bindings
	// AllCmds is called to retrieve all commands.
	AllCmds func() ([]store.Cmd, error)
	// Dedup is called to determine whether deduplication should be done.
	// Defaults to true if unset.
	Dedup func() bool
	// Configuration for the filter.
	Filter FilterSpec
}

// NewHistlist creates a new histlist mode.
func ( cli.App,  HistlistSpec) (Histlist, error) {
	if .AllCmds == nil {
		return nil, errNoHistoryStore
	}
	if .Dedup == nil {
		.Dedup = func() bool { return true }
	}

	,  := .AllCmds()
	if  != nil {
		return nil, fmt.Errorf("db error: %v", .Error())
	}
	 := map[string]int{}
	for ,  := range  {
		[.Text] = 
	}
	 := histlistItems{, }

	 := tk.NewComboBox(tk.ComboBoxSpec{
		CodeArea: tk.CodeAreaSpec{
			Prompt: func() ui.Text {
				 := " HISTORY "
				if .Dedup() {
					 += "(dedup on) "
				}
				return modeLine(, true)
			},
			Highlighter: .Filter.Highlighter,
		},
		ListBox: tk.ListBoxSpec{
			Bindings: .Bindings,
			OnAccept: func( tk.Items,  int) {
				 := .(histlistItems).entries[].Text
				.CodeArea().MutateState(func( *tk.CodeAreaState) {
					 := &.Buffer
					if .Content == "" {
						.InsertAtDot()
					} else {
						.InsertAtDot("\n" + )
					}
				})
				.SetAddon(nil, false)
			},
		},
		OnFilter: func( tk.ComboBox,  string) {
			 := .filter(.Filter.makePredicate(), .Dedup())
			.ListBox().Reset(, .Len()-1)
		},
	})
	return , nil
}

type histlistItems struct {
	entries []store.Cmd
	last    map[string]int
}

func ( histlistItems) ( func(string) bool,  bool) histlistItems {
	var  []store.Cmd
	for ,  := range .entries {
		 := .Text
		if  && .last[] !=  {
			continue
		}
		if () {
			 = append(, )
		}
	}
	return histlistItems{, nil}
}

func ( histlistItems) ( int) ui.Text {
	 := .entries[]
	// TODO: The alignment of the index works up to 10000 entries.
	return ui.T(fmt.Sprintf("%4d %s", .Seq, .Text))
}

func ( histlistItems) () int { return len(.entries) }