package mode

import (
	

	
	
	
	
)

// Instant is a mode that executes code whenever it changes and shows the
// result.
type Instant interface {
	tk.Widget
}

// InstantSpec specifies the configuration for the instant mode.
type InstantSpec struct {
	// Key bindings.
	Bindings tk.Bindings
	// The function to execute code and returns the output.
	Execute func(code string) ([]string, error)
}

type instant struct {
	InstantSpec
	app      cli.App
	textView tk.TextView
	lastCode string
	lastErr  error
}

func ( *instant) (,  int) *term.Buffer {
	 := term.NewBufferBuilder().
		WriteStyled(modeLine(" INSTANT ", false)).SetDotHere()
	if .lastErr != nil {
		.Newline().Write(.lastErr.Error(), ui.FgRed)
	}
	 := .Buffer()
	if len(.Lines) >=  {
		.TrimToLines(0, )
		return 
	}
	 := .textView.Render(, -len(.Lines))
	.Extend(, false)
	return 
}

func ( *instant) () bool { return false }

func ( *instant) ( term.Event) bool {
	 := .Bindings.Handle(, )
	if ! {
		 := .app.CodeArea()
		 = .Handle()
	}
	.update(false)
	return 
}

func ( *instant) ( bool) {
	 := .app.CodeArea().CopyState().Buffer.Content
	if  == .lastCode && ! {
		return
	}
	.lastCode = 
	,  := .Execute()
	.lastErr = 
	if  == nil {
		.textView.MutateState(func( *tk.TextViewState) {
			* = tk.TextViewState{Lines: , First: 0}
		})
	}
}

var errExecutorIsRequired = errors.New("executor is required")

// NewInstant creates a new instant mode.
func ( cli.App,  InstantSpec) (Instant, error) {
	if .Execute == nil {
		return nil, errExecutorIsRequired
	}
	if .Bindings == nil {
		.Bindings = tk.DummyBindings{}
	}
	 := instant{
		InstantSpec: ,
		app:         ,
		textView:    tk.NewTextView(tk.TextViewSpec{Scrollable: true}),
	}
	.update(true)
	return &, nil
}