package cview

import (
	

	
)

// Modal is a centered message window used to inform the user or prompt them
// for an immediate decision. It needs to have at least one button (added via
// AddButtons) or it will never disappear. You may change the title and
// appearance of the window by modifying the Frame returned by GetFrame. You
// may include additional elements within the window by modifying the Form
// returned by GetForm.
type Modal struct {
	*Box

	// The Frame embedded in the Modal.
	frame *Frame

	// The Form embedded in the Modal's Frame.
	form *Form

	// The message text (original, not word-wrapped).
	text string

	// The text color.
	textColor tcell.Color

	// The text alignment.
	textAlign int

	// The optional callback for when the user clicked one of the buttons. It
	// receives the index of the clicked button and the button's label.
	done func(buttonIndex int, buttonLabel string)

	sync.RWMutex
}

// NewModal returns a new centered message window.
func () *Modal {
	 := &Modal{
		Box:       NewBox(),
		textColor: Styles.PrimaryTextColor,
		textAlign: AlignCenter,
	}

	.form = NewForm()
	.form.SetButtonsAlign(AlignCenter)
	.form.SetPadding(0, 0, 0, 0)
	.form.SetCancelFunc(func() {
		if .done != nil {
			.done(-1, "")
		}
	})

	.frame = NewFrame(.form)
	.frame.SetBorder(true)
	.frame.SetBorders(0, 0, 1, 0, 0, 0)
	.frame.SetPadding(1, 1, 1, 1)

	.focus = 
	return 
}

// SetBackgroundColor sets the color of the Modal Frame background.
func ( *Modal) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.form.SetBackgroundColor()
	.frame.SetBackgroundColor()
}

// SetTextColor sets the color of the message text.
func ( *Modal) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.textColor = 
}

// SetButtonBackgroundColor sets the background color of the buttons.
func ( *Modal) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.form.SetButtonBackgroundColor()
}

// SetButtonTextColor sets the color of the button texts.
func ( *Modal) ( tcell.Color) {
	.Lock()
	defer .Unlock()

	.form.SetButtonTextColor()
}

// SetButtonsAlign sets the horizontal alignment of the buttons. This must be
// either AlignLeft, AlignCenter (the default), or AlignRight.
func ( *Modal) ( int) {
	.Lock()
	defer .Unlock()

	.form.SetButtonsAlign()
}

// SetDoneFunc sets a handler which is called when one of the buttons was
// pressed. It receives the index of the button as well as its label text. The
// handler is also called when the user presses the Escape key. The index will
// then be negative and the label text an empty string.
func ( *Modal) ( func( int,  string)) {
	.Lock()
	defer .Unlock()

	.done = 
}

// SetText sets the message text of the window. The text may contain line
// breaks. Note that words are wrapped, too, based on the final size of the
// window.
func ( *Modal) ( string) {
	.Lock()
	defer .Unlock()

	.text = 
}

// SetTextAlign sets the horizontal alignment of the text. This must be either
// AlignLeft, AlignCenter (the default), or AlignRight.
func ( *Modal) ( int) {
	.Lock()
	defer .Unlock()

	.textAlign = 
}

// GetForm returns the Form embedded in the window. The returned Form may be
// modified to include additional elements (e.g. AddInputField, AddFormItem).
func ( *Modal) () *Form {
	.RLock()
	defer .RUnlock()

	return .form
}

// GetFrame returns the Frame embedded in the window.
func ( *Modal) () *Frame {
	.RLock()
	defer .RUnlock()

	return .frame
}

// AddButtons adds buttons to the window. There must be at least one button and
// a "done" handler so the window can be closed again.
func ( *Modal) ( []string) {
	.Lock()
	defer .Unlock()

	for ,  := range  {
		func( int,  string) {
			.form.AddButton(, func() {
				if .done != nil {
					.done(, )
				}
			})
			 := .form.GetButton(.form.GetButtonCount() - 1)
			.SetInputCapture(func( *tcell.EventKey) *tcell.EventKey {
				switch .Key() {
				case tcell.KeyDown, tcell.KeyRight:
					return tcell.NewEventKey(tcell.KeyTab, 0, tcell.ModNone)
				case tcell.KeyUp, tcell.KeyLeft:
					return tcell.NewEventKey(tcell.KeyBacktab, 0, tcell.ModNone)
				}
				return 
			})
		}(, )
	}
}

// ClearButtons removes all buttons from the window.
func ( *Modal) () {
	.Lock()
	defer .Unlock()

	.form.ClearButtons()
}

// SetFocus shifts the focus to the button with the given index.
func ( *Modal) ( int) {
	.Lock()
	defer .Unlock()

	.form.SetFocus()
}

// Focus is called when this primitive receives focus.
func ( *Modal) ( func( Primitive)) {
	(.form)
}

// HasFocus returns whether or not this primitive has focus.
func ( *Modal) () bool {
	return .GetForm().HasFocus()
}

// Draw draws this primitive onto the screen.
func ( *Modal) ( tcell.Screen) {
	if !.GetVisible() {
		return
	}

	 := .form.GetFormItemCount()

	.Lock()
	defer .Unlock()

	// Calculate the width of this Modal.
	 := 0
	for ,  := range .form.buttons {
		 += TaggedTextWidth(.label) + 4 + 2
	}
	 -= 2
	,  := .Size()
	 :=  / 3
	if  <  {
		 = 
	}
	// width is now without the box border.

	// Reset the text and find out how wide it is.
	.frame.Clear()
	 := WordWrap(.text, )
	for ,  := range  {
		.frame.AddText(, true, .textAlign, .textColor)
	}

	// Set the Modal's position and size.
	 := len() + ( * 2) + 6
	 += 4
	 := ( - ) / 2
	 := ( - ) / 2
	.SetRect(, , , )

	// Draw the frame.
	.frame.SetRect(, , , )
	.frame.Draw()
}

// MouseHandler returns the mouse handler for this primitive.
func ( *Modal) () func( MouseAction,  *tcell.EventMouse,  func( Primitive)) ( bool,  Primitive) {
	return .WrapMouseHandler(func( MouseAction,  *tcell.EventMouse,  func( Primitive)) ( bool,  Primitive) {
		// Pass mouse events on to the form.
		,  = .form.MouseHandler()(, , )
		if ! &&  == MouseLeftClick && .InRect(.Position()) {
			()
			 = true
		}
		return
	})
}